Skip to content

Commit

Permalink
Merge pull request #134 from evandor/TAB-481-github-sync
Browse files Browse the repository at this point in the history
Tab 481 GitHub sync
  • Loading branch information
evandor authored Jan 26, 2024
2 parents 6c4ef27 + 534cf24 commit 76d3d36
Show file tree
Hide file tree
Showing 108 changed files with 7,800 additions and 2,033 deletions.
7 changes: 7 additions & 0 deletions .env.template
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,10 @@ FIREBASE_API_KEY="..."
COUCHDB_PWD=...
COUCHDB_URL=cdb.skysail.io
COUCHDB_PROTOCOL=https://

PUBLIC_FIREBASE_API_KEY="AIz..."
PUBLIC_FIREBASE_AUTH_DOMAIN=....firebaseapp.com"
PUBLIC_FIREBASE_PROJECT_ID="..."
PUBLIC_FIREBASE_STORAGE_BUCKET="....appspot.com"
PUBLIC_FIREBASE_MESSAGING_SENDER_ID="65..."
PUBLIC_FIREBASE_APP_ID="1:65...8:web:6...b"
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ node_modules
/src-cordova/www

# Capacitor related directories and files
/src-capacitor/www
/src-capacitor/node_modules
/src-capacitor2/www
/src-capacitor2/node_modules

# BEX related directories and files
/src-bex/www
Expand Down
1 change: 1 addition & 0 deletions docs/authorization.drawio
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<mxfile host="drawio-plugin" modified="2024-01-15T18:27:22.843Z" agent="5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36" etag="zVLa5IalWynmGP_QGqDB" version="20.5.3" type="embed"><diagram id="23iRSUPoRavnBvh4doch" name="Page-1"><mxGraphModel dx="1465" dy="1174" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0"><root><mxCell id="0"/><mxCell id="1" parent="0"/><mxCell id="3" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"><mxGeometry x="190" y="130" width="120" height="360" as="geometry"/></mxCell><mxCell id="4" value="SidePanel" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1"><mxGeometry x="220" y="80" width="60" height="30" as="geometry"/></mxCell><mxCell id="6" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"><mxGeometry x="50" y="130" width="120" height="360" as="geometry"/></mxCell><mxCell id="7" value="Welcome Page (?)" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1"><mxGeometry x="80" y="80" width="60" height="30" as="geometry"/></mxCell><mxCell id="10" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="8" target="9"><mxGeometry relative="1" as="geometry"><Array as="points"><mxPoint x="280" y="570"/></Array></mxGeometry></mxCell><mxCell id="31" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.75;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="8" target="33"><mxGeometry relative="1" as="geometry"><mxPoint x="254.01" y="548" as="targetPoint"/></mxGeometry></mxCell><mxCell id="8" value="Login" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1"><mxGeometry x="255" y="466" width="50" height="20" as="geometry"/></mxCell><mxCell id="9" value="Firebase" style="shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;" vertex="1" parent="1"><mxGeometry x="440" y="540" width="120" height="60" as="geometry"/></mxCell><mxCell id="11" value="sendSignInLinkToEmail" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1"><mxGeometry x="280" y="540" width="150" height="30" as="geometry"/></mxCell><mxCell id="12" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"><mxGeometry x="321" y="130" width="380" height="360" as="geometry"/></mxCell><mxCell id="13" value="Main" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1"><mxGeometry x="480" y="80" width="60" height="30" as="geometry"/></mxCell><mxCell id="15" value="" style="html=1;verticalLabelPosition=bottom;align=center;labelBackgroundColor=#ffffff;verticalAlign=top;strokeWidth=2;strokeColor=#0080F0;shadow=0;dashed=0;shape=mxgraph.ios7.icons.mail;" vertex="1" parent="1"><mxGeometry x="460" y="510" width="30" height="16.5" as="geometry"/></mxCell><mxCell id="16" value="click on Link, redirecting to&amp;nbsp;&lt;br&gt;tabsets" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1"><mxGeometry x="520" y="503.25" width="210" height="30" as="geometry"/></mxCell><mxCell id="20" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="17" target="19"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="17" value="&lt;b&gt;ChromeListener&lt;/b&gt;&lt;br&gt;checkOriginForEmailLink" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"><mxGeometry x="385" y="410" width="230" height="40" as="geometry"/></mxCell><mxCell id="14" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="1" source="9" target="17"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="19" value="&lt;b&gt;AuthStore&lt;/b&gt;&lt;br&gt;setAuthRequest(authRequest)" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"><mxGeometry x="385" y="330" width="230" height="40" as="geometry"/></mxCell><mxCell id="23" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;dashed=1;" edge="1" parent="1" source="21" target="19"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="26" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="21" target="24"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="21" value="Watch &lt;br&gt;AuthRequest" style="shape=hexagon;perimeter=hexagonPerimeter2;whiteSpace=wrap;html=1;fixedSize=1;size=10;" vertex="1" parent="1"><mxGeometry x="200" y="410" width="100" height="40" as="geometry"/></mxCell><mxCell id="22" value="Watch &lt;br&gt;AuthRequest" style="shape=hexagon;perimeter=hexagonPerimeter2;whiteSpace=wrap;html=1;fixedSize=1;size=10;" vertex="1" parent="1"><mxGeometry x="60" y="410" width="100" height="40" as="geometry"/></mxCell><mxCell id="28" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="24" target="27"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="24" value="reload page with&lt;br&gt;authRequest Params" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1"><mxGeometry x="205" y="330" width="90" height="65" as="geometry"/></mxCell><mxCell id="30" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="27" target="29"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="32" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.25;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="27" target="33"><mxGeometry relative="1" as="geometry"><mxPoint x="180" y="533" as="targetPoint"/><Array as="points"><mxPoint x="180" y="284"/></Array></mxGeometry></mxCell><mxCell id="27" value="&lt;b&gt;App.vue&lt;/b&gt;&lt;br&gt;is SignIn Link?&lt;br&gt;authStore: save User" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"><mxGeometry x="195" y="253" width="110" height="62" as="geometry"/></mxCell><mxCell id="36" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="29" target="35"><mxGeometry relative="1" as="geometry"/></mxCell><mxCell id="29" value="Watch &lt;br&gt;User" style="shape=hexagon;perimeter=hexagonPerimeter2;whiteSpace=wrap;html=1;fixedSize=1;size=10;" vertex="1" parent="1"><mxGeometry x="200" y="193" width="100" height="40" as="geometry"/></mxCell><mxCell id="33" value="&lt;span style=&quot;&quot;&gt;remember email&lt;/span&gt;" style="whiteSpace=wrap;html=1;" vertex="1" parent="1"><mxGeometry x="150" y="550" width="120" height="30" as="geometry"/></mxCell><mxCell id="34" value="check" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1"><mxGeometry x="130" y="503.25" width="60" height="30" as="geometry"/></mxCell><mxCell id="35" value="Account" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.database;whiteSpace=wrap;" vertex="1" parent="1"><mxGeometry x="207" y="133" width="85" height="40" as="geometry"/></mxCell></root></mxGraphModel></diagram></mxfile>
84 changes: 84 additions & 0 deletions docs/authorization.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
### Login

e.g. in SidePanelFooter

```js
const signin = () => {
...
sendSignInLinkToEmail(auth, email.value, actionCodeSettings)
.then(() => {
...
window.localStorage.setItem(CURRENT_USER_EMAIL, email.value);
sendMsg('SET_EMAIL_FOR_SIGN_IN', {"email": email.value})
})
}
```

A mail is created by firebase, redirecting to a page defined in actionCodeSettings ("https://tabsets.web.app")

### Email opened in Browser

In ChromeListener, the extension listens on tab updates and checks the url for the email link (when a new tab is opened as the user clicks on the email link)

```js
async onUpdated(number: number, info: chrome.tabs.TabChangeInfo, chromeTab: chrome.tabs.Tab) {
if (info.url) {
const emailLink = info.url;
const urlOrigin = new URL(emailLink).origin;

if (this.checkOriginForEmailLink(urlOrigin)) {
const split = emailLink.split("?")
const authRequest = split[1]
useAuthStore().setAuthRequest(authRequest)
}
}
...
}
```

The authRequest (something like apiKey=AIz...kY&oobCode=1...w&mode=signIn&lang=en) is stored in the authStore

### Listening to the authStore

In SidePanelPage.vue and WelcomePage.vue, there is a watch on the authRequest:

```js
watchEffect(() => {
const ar = useAuthStore().useAuthRequest
if (ar) {
if (window.location.href.indexOf("?") < 0) {
const tsIframe = window.parent.frames[0]
console.log("iframe", tsIframe)
if (tsIframe) {
tsIframe.location.href = window.location.href + "?" + ar
tsIframe.location.reload()
}
}
}
})

```

"useAuthRequest" will retrieve the authRequest once (by setting it to null)

### Last Step

In App.vue, we have

```js
if (isSignInWithEmailLink(getAuth(), window.location.href)) {
const emailForSignIn = LocalStorage.getItem("emailForSignIn")
signInWithEmailLink(auth, emailForSignIn, window.location.href)
.then((result: UserCredential) => {
useAuthStore().setUser(result.user)
})
}

```

### todos

check if isSignInWithEmailLink can be used before in checkOriginForEmailLink
we have duplicate code in SidePanelPage.vue and WelcomePage.vue
getDoc in SidePanel (check and document)
use /refresh redirect to open authenticated page?
13 changes: 10 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@
"dev ssr": "quasar dev -m ssr",
"dev stage prod": "stage=production quasar dev -m bex",
"dev electron": "quasar dev -m electron",
"dev capacitor": "quasar dev -m capacitor -T ios",
"dev cordova": "quasar dev -m cordova -T ios",
"build": "quasar build -m bex",
"build pwa": "quasar build -m pwa",
"build electron": "quasar build -m electron",
"build capacitor": "quasar build -m capacitor -T ios",
"icon": "icongenie generate -i src/assets/icon.png",
"test": "echo \"See package.json => scripts for available tests.\" && exit 0",
"test:unit:ui": "vitest --ui",
Expand All @@ -37,8 +40,10 @@
"@editorjs/header": "^2.7.0",
"@extractus/feed-extractor": "^7.0.1",
"@isomorphic-git/lightning-fs": "^4.6.0",
"@logtail/browser": "^0.4.19",
"@mozilla/readability": "^0.5.0",
"@quasar/extras": "^1.16.6",
"@stripe/stripe-js": "^2.2.2",
"@types/lodash": "^4.14.182",
"@types/pngjs": "^6.0.4",
"@types/pouchdb": "^6.4.2",
Expand All @@ -50,6 +55,7 @@
"date-fns": "^3.1.0",
"dotenv": "^16.0.1",
"events": "^3.3.0",
"firebase": "^10.7.1",
"fuse.js": "^7.0.0",
"html-to-text": "^9.0.4",
"idb": "^8.0.0",
Expand Down Expand Up @@ -84,6 +90,7 @@
"devDependencies": {
"@babel/preset-env": "^7.19.0",
"@calumk/editorjs-codeflask": "^1.0.9",
"@capacitor/cli": "^5.6.0",
"@editorjs/checklist": "^1.5.0",
"@editorjs/image": "^2.9.0",
"@editorjs/link": "^2.5.0",
Expand All @@ -99,8 +106,8 @@
"@types/pixelmatch": "^5.2.6",
"@types/uuid": "^9.0.1",
"@vitest/coverage-c8": "^0.33.0",
"@vitest/coverage-v8": "^1.1.3",
"@vitest/ui": "^1.1.3",
"@vitest/coverage-v8": "^0.34.3",
"@vitest/ui": "^0.34.3",
"@vue/test-utils": "^2.4.1",
"@wdio/cli": "^8.13.5",
"autoprefixer": "^10.4.2",
Expand All @@ -111,7 +118,7 @@
"electron-packager": "^17.1.1",
"fake-indexeddb": "^5.0.1",
"typescript": "^5.1.6",
"vitest": "^1.1.3",
"vitest": "^0.34.0",
"workbox-build": "^7.0.0",
"workbox-cacheable-response": "^7.0.0",
"workbox-core": "^7.0.0",
Expand Down
2 changes: 1 addition & 1 deletion public/sidepanel.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@

</head>
<body>
<iframe src="/www/index.html" style="position: absolute; height: 100%; width:100%;border: none"></iframe>
<iframe id="ts-sidepanel-frame" src="/www/index.html" style="position: absolute; height: 100%; width:100%;border: none"></iframe>
</body>
</html>
16 changes: 13 additions & 3 deletions quasar.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ module.exports = configure(function (ctx) {
boot: [
//'i18n',
'constants',
'auth0'
'firebase',
// 'auth0',
'logtail'
],

// https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#css
Expand Down Expand Up @@ -85,7 +87,11 @@ module.exports = configure(function (ctx) {
STRIPE_PUBLISHABLE_KEY: process.env.STRIPE_PUBLISHABLE_KEY,
STRIPE_ACCOUNT: process.env.STRIPE_ACCOUNT,
STRIPE_API_VERSION: process.env.STRIPE_API_VERSION,
LOCALE: process.env.LOCALE
LOCALE: process.env.LOCALE,
FIREBASE_API_KEY: process.env.FIREBASE_API_KEY,
FIREBASE_AUTH_DOMAIN: process.env.FIREBASE_AUTH_DOMAIN,
FIREBASE_PROJECT_ID: process.env.FIREBASE_PROJECT_ID,
FIREBASE_APP_ID: process.env.FIREBASE_APP_ID
},
// rawDefine: {}
// ignorePublicFolder: true,
Expand All @@ -95,9 +101,13 @@ module.exports = configure(function (ctx) {

// !== MIT
extendViteConf (viteConf) {
if ((ctx.mode.spa || ctx.mode.pwa || ctx.mode.electron) && viteConf && viteConf.mode === "development") {
console.log("******",ctx.mode)
//if ((ctx.mode.spa || ctx.mode.pwa || ctx.mode.electron) && viteConf && viteConf.mode === "development") {
if (!ctx.mode.bex && !ctx.mode.pwa) {
// https://dev.to/richardbray/how-to-fix-the-referenceerror-global-is-not-defined-error-in-sveltekitvite-2i49
viteConf.define.global = {}
//https://stackoverflow.com/questions/77061323/error-pouchdb-on-vite-referenceerror-global-is-not-defined
//viteConf.define.window.global = window.global
}
viteConf.define.__VUE_PROD_HYDRATION_MISMATCH_DETAILS__ = 'false'
},
Expand Down
7 changes: 7 additions & 0 deletions src-bex/content-script.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// More info: https://quasar.dev/quasar-cli/developing-browser-extensions/content-hooks
// @ts-ignore
import {bexContent} from 'quasar/wrappers'
import {CURRENT_USER_EMAIL} from "boot/constants";

export default bexContent((bridge: any) => {

Expand Down Expand Up @@ -29,6 +30,7 @@ export default bexContent((bridge: any) => {
})

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
console.log("tabsets: hier", request)
if (request === 'getContent') {
console.log("tabsets: received message for content", document.documentElement.outerHTML)
sendResponse({content: document.documentElement.outerHTML});
Expand All @@ -45,6 +47,11 @@ export default bexContent((bridge: any) => {
// csIframe.style.right = "5px"
// csIframe.style.top = "75px"
}
else if (request.type === "SET_EMAIL_FOR_SIGN_IN") {
chrome.storage.local.set({ CURRENT_USER_EMAIL: request.email });
chrome.storage.local.set({ tabext: sender.tab });
console.log("SET_EMAIL_FOR_SIGN_IN", request.email);
}
sendResponse({content: "unknown request in content-scripts: " + request});
return true
})
Expand Down
7 changes: 7 additions & 0 deletions src-bex/tabsets-content-script.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// More info: https://quasar.dev/quasar-cli/developing-browser-extensions/content-hooks
// @ts-ignore
import {bexContent} from 'quasar/wrappers'
import {CURRENT_USER_EMAIL} from "boot/constants";


export default bexContent((bridge: any) => {
Expand All @@ -19,12 +20,18 @@ export default bexContent((bridge: any) => {


chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
console.log("got request!!!", request)
if (request === 'getContent') {
console.log("tabsets: received message for content", document.documentElement.outerHTML)
sendResponse({content: document.documentElement.outerHTML});
} else if (request.action === "highlight-annotation") {
sendResponse()
}
else if (request.type === "SET_EMAIL_FOR_SIGN_IN") {
chrome.storage.local.set({ CURRENT_USER_EMAIL: request.email });
chrome.storage.local.set({ tabext: sender.tab });
console.log("SET_EMAIL_FOR_SIGN_IN", request.email);
}
sendResponse({content: "unknown request in tabsets-content-scripts: " + request});
return true
})
Expand Down
10 changes: 10 additions & 0 deletions src-capacitor/capacitor-flag.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/* eslint-disable */
// THIS FEATURE-FLAG FILE IS AUTOGENERATED,
// REMOVAL OR CHANGES WILL CAUSE RELATED TYPES TO STOP WORKING
import "quasar/dist/types/feature-flag";

declare module "quasar/dist/types/feature-flag" {
interface QuasarFeatureFlags {
capacitor: true;
}
}
9 changes: 9 additions & 0 deletions src-capacitor/capacitor.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"appId": "io.skysail.tabsets",
"appName": "Tabsets - Manage Tabs and Bookmarks with Ease",
"webDir": "www",
"server": {
"androidScheme": "https",
"url": "http://192.168.178.112:9500"
}
}
35 changes: 35 additions & 0 deletions src-capacitor/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<!DOCTYPE html>
<html>
<head>
<title>Quasar</title>

<meta charset="utf-8">
<meta name="description" content="Quasar Capacitor App">
<meta name="format-detection" content="telephone=no">
<meta name="msapplication-tap-highlight" content="no">
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, viewport-fit=cover">

<style>
.page {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
text-align: center;
}
</style>
</head>

<body>
<div class="page">
<div>
This file will be auto-generated. Do not edit.
</div>

<div>
Run "quasar dev" or "quasar build" with Capacitor mode.
</div>
</div>
</body>
</html>
13 changes: 13 additions & 0 deletions src-capacitor/ios/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
App/build
App/Pods
App/output
App/App/public
DerivedData
xcuserdata

# Cordova plugins for Capacitor
capacitor-cordova-ios-plugins

# Generated Config files
App/App/capacitor.config.json
App/App/config.xml
Loading

0 comments on commit 76d3d36

Please sign in to comment.