From a7ade501f7c85632208c74e3553305c815159d01 Mon Sep 17 00:00:00 2001
From: Shin'ya UEOKA <ueokande@i-beam.org>
Date: Sun, 9 May 2021 02:37:54 +0000
Subject: Support reader-mode

---
 src/@types/web-ext-api/index.d.ts                         |  4 ++++
 src/background/operators/impls/TabOperatorFactoryChain.ts |  3 +++
 src/background/operators/impls/ToggleReaderOperator.ts    | 11 +++++++++++
 src/background/presenters/TabPresenter.ts                 |  6 ++++++
 src/shared/operations.ts                                  |  7 +++++++
 5 files changed, 31 insertions(+)
 create mode 100644 src/background/operators/impls/ToggleReaderOperator.ts

diff --git a/src/@types/web-ext-api/index.d.ts b/src/@types/web-ext-api/index.d.ts
index 7eed334..c2ffbb2 100644
--- a/src/@types/web-ext-api/index.d.ts
+++ b/src/@types/web-ext-api/index.d.ts
@@ -1,3 +1,7 @@
+declare namespace browser.tabs {
+  function toggleReaderMode(tabId?: number): Promise<void>;
+}
+
 declare namespace browser.browserSettings.homepageOverride {
   type BrowserSettings = {
     value: string;
diff --git a/src/background/operators/impls/TabOperatorFactoryChain.ts b/src/background/operators/impls/TabOperatorFactoryChain.ts
index edd3eaf..d526f86 100644
--- a/src/background/operators/impls/TabOperatorFactoryChain.ts
+++ b/src/background/operators/impls/TabOperatorFactoryChain.ts
@@ -16,6 +16,7 @@ import PinTabOperator from "./PinTabOperator";
 import UnpinTabOperator from "./UnpinTabOperator";
 import TogglePinnedTabOperator from "./TogglePinnedTabOperator";
 import DuplicateTabOperator from "./DuplicateTabOperator";
+import ToggleReaderOperator from "./ToggleReaderOperator";
 
 @injectable()
 export default class TabOperatorFactoryChain implements OperatorFactoryChain {
@@ -58,6 +59,8 @@ export default class TabOperatorFactoryChain implements OperatorFactoryChain {
         return new TogglePinnedTabOperator(this.tabPresenter);
       case operations.TAB_DUPLICATE:
         return new DuplicateTabOperator(this.tabPresenter);
+      case operations.TAB_TOGGLE_READER:
+        return new ToggleReaderOperator(this.tabPresenter);
     }
     return null;
   }
diff --git a/src/background/operators/impls/ToggleReaderOperator.ts b/src/background/operators/impls/ToggleReaderOperator.ts
new file mode 100644
index 0000000..681e4c3
--- /dev/null
+++ b/src/background/operators/impls/ToggleReaderOperator.ts
@@ -0,0 +1,11 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class ToggleReaderOperator implements Operator {
+  constructor(private readonly tabPresenter: TabPresenter) {}
+
+  async run(): Promise<void> {
+    const tab = await this.tabPresenter.getCurrent();
+    return this.tabPresenter.toggleReaderMode(tab.id as number);
+  }
+}
diff --git a/src/background/presenters/TabPresenter.ts b/src/background/presenters/TabPresenter.ts
index 2f8f5d9..ef4b343 100644
--- a/src/background/presenters/TabPresenter.ts
+++ b/src/background/presenters/TabPresenter.ts
@@ -47,6 +47,8 @@ export default interface TabPresenter {
   onSelected(
     listener: (arg: { tabId: number; windowId: number }) => void
   ): void;
+
+  toggleReaderMode(tabId: number): Promise<void>;
 }
 
 export class TabPresenterImpl implements TabPresenter {
@@ -152,6 +154,10 @@ export class TabPresenterImpl implements TabPresenter {
   ): void {
     browser.tabs.onActivated.addListener(listener);
   }
+
+  toggleReaderMode(tabId: number): Promise<void> {
+    return browser.tabs.toggleReaderMode(tabId);
+  }
 }
 
 const tabPresenter = new TabPresenterImpl();
diff --git a/src/shared/operations.ts b/src/shared/operations.ts
index 3544502..1433011 100644
--- a/src/shared/operations.ts
+++ b/src/shared/operations.ts
@@ -56,6 +56,7 @@ export const TAB_PIN = "tabs.pin";
 export const TAB_UNPIN = "tabs.unpin";
 export const TAB_TOGGLE_PINNED = "tabs.pin.toggle";
 export const TAB_DUPLICATE = "tabs.duplicate";
+export const TAB_TOGGLE_READER = "tabs.reader.toggle";
 
 // Zooms
 export const ZOOM_IN = "zoom.in";
@@ -257,6 +258,10 @@ export interface TabDuplicateOperation {
   type: typeof TAB_DUPLICATE;
 }
 
+export interface TabToggleReaderOperation {
+  type: typeof TAB_TOGGLE_READER;
+}
+
 export interface ZoomInOperation {
   type: typeof ZOOM_IN;
 }
@@ -352,6 +357,7 @@ export type Operation =
   | TabUnpinOperation
   | TabTogglePinnedOperation
   | TabDuplicateOperation
+  | TabToggleReaderOperation
   | ZoomInOperation
   | ZoomOutOperation
   | ZoomNeutralOperation
@@ -506,6 +512,7 @@ export const valueOf = (o: any): Operation => {
     case TAB_UNPIN:
     case TAB_TOGGLE_PINNED:
     case TAB_DUPLICATE:
+    case TAB_TOGGLE_READER:
     case ZOOM_IN:
     case ZOOM_OUT:
     case ZOOM_NEUTRAL:
-- 
cgit v1.2.3


From a462f3c4d0a6c9abc152042be8cd8bb473fdfbba Mon Sep 17 00:00:00 2001
From: Shin'ya Ueoka <ueokande@i-beam.org>
Date: Sun, 9 May 2021 11:58:40 +0900
Subject: Add reader-view keymaps to gr

---
 src/settings/keymaps.ts         | 1 +
 src/shared/settings/Settings.ts | 1 +
 2 files changed, 2 insertions(+)

diff --git a/src/settings/keymaps.ts b/src/settings/keymaps.ts
index 25c7a51..ff87cf4 100644
--- a/src/settings/keymaps.ts
+++ b/src/settings/keymaps.ts
@@ -31,6 +31,7 @@ const fields = [
     ['tabs.reload?{"cache":true}', "Reload with no caches"],
     ["tabs.pin.toggle", "Toggle pinned state"],
     ["tabs.duplicate", "Duplicate a tab"],
+    ["tabs.reader.toggle", "Reader view"],
   ],
   [
     ['follow.start?{"newTab":false,"background":false}', "Follow a link"],
diff --git a/src/shared/settings/Settings.ts b/src/shared/settings/Settings.ts
index 43297a3..6c4fa0a 100644
--- a/src/shared/settings/Settings.ts
+++ b/src/shared/settings/Settings.ts
@@ -133,6 +133,7 @@ export const DefaultSettingJSONText = `{
     "gf": { "type": "page.source" },
     "gh": { "type": "page.home" },
     "gH": { "type": "page.home", "newTab": true },
+    "gr": { "type": "tabs.reader.toggle" },
     "y": { "type": "urls.yank" },
     "p": { "type": "urls.paste", "newTab": false },
     "P": { "type": "urls.paste", "newTab": true },
-- 
cgit v1.2.3


From 410189d7499886b1ac5d8e12a4fe76863cc28934 Mon Sep 17 00:00:00 2001
From: Shin'ya Ueoka <ueokande@i-beam.org>
Date: Sun, 9 May 2021 15:04:50 +0900
Subject: Add reader-view test

---
 e2e/tab.test.ts | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/e2e/tab.test.ts b/e2e/tab.test.ts
index 49d1c03..b59c246 100644
--- a/e2e/tab.test.ts
+++ b/e2e/tab.test.ts
@@ -107,6 +107,20 @@ describe("tab test", () => {
     assert.strictEqual(current[0].pinned, true);
   });
 
+  it("switches to reader view", async () => {
+    await browser.tabs.update(tabs[0].id, { active: true });
+    const page = await Page.currentContext(webdriver);
+    await page.sendKeys("g", "r");
+
+    // Unable to switch to reader view, but an error message occurs
+    const console = await page.getConsole();
+    const errorMessage = await console.getErrorMessage();
+    assert.strictEqual(
+      errorMessage,
+      "The specified tab cannot be placed into reader mode."
+    );
+  });
+
   it("selects previous tab by K", async () => {
     await browser.tabs.update(tabs[2].id, { active: true });
     const page = await Page.currentContext(webdriver);
-- 
cgit v1.2.3