Skip to content

Commit

Permalink
Initial Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
D3VL-Jack committed Jul 15, 2023
0 parents commit 657aebb
Show file tree
Hide file tree
Showing 33 changed files with 1,448 additions and 0 deletions.
28 changes: 28 additions & 0 deletions .github/actions/build-extension.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Github Action that builds react extension and creates a zip file for deployment, updates the version in manifest.json from package.json and creates a release in github with the zip file
build-extension:
name: Build Extension
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v1
with:
node-version: 20.x
- name: Install Dependencies
run: npm install
- name: Update Manifest
run: npm run update-manifest
- name: Build Extension
run: npm run build
- name: get-npm-version
id: package-version
uses: martinbeentjes/[email protected]
- name: Zip Extension
run: zip -r ${{ steps.package-version.outputs.current-version}}.zip build
- name: Create Release
run: |
gh release create ${{ steps.package-version.outputs.current-version}} -F ${{ steps.package-version.outputs.current-version}}.zip
gh release upload ${{ steps.package-version.outputs.current-version}} ${{ steps.package-version.outputs.current-version}}.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
25 changes: 25 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# production
/build

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*

package-lock.json
45 changes: 45 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"name": "youtrack-time-tracker",
"version": "1.0.0",
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1"
},
"devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.0",
"react-router-dom": "^6.14.1",
"tailwindcss": "^3.3.2"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"update-manifest": "node ./scripts/update-manifest.js"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
],
"env": {
"webextensions": true
},
"globals": {
"chrome": true
}
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
16 changes: 16 additions & 0 deletions public/background.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
// proxy for fetch requests
if (request.type === 'fetch') {
fetch(request.url, request.options).then((response) => {
if (!response.ok) {
sendResponse({ error: response.statusText });
} else {
response.json().then((json) => { sendResponse({ response: json }) }).catch((error) => { sendResponse({ error: error.message }) });
}
}).catch((error) => {
sendResponse({ error: error.message });
});

return true;
}
});
Binary file added public/images/128x128_dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/128x128_light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/16x16_dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/16x16_light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/48x48_dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/48x48_light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/icon_dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/images/icon_dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/icon_light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/images/icon_light.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no" />
<meta name="theme-color" content="#101827" />
<meta name="description" content="Web site created using create-react-app" />
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<title>YouTrack Timer</title>
</head>

<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>

</html>
23 changes: 23 additions & 0 deletions public/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"manifest_version": 3,
"version": "=version=",
"name": "YouTrack Timer",
"action": {
"default_icon": {
"16": "images/16x16_light.png",
"48": "images/48x48_light.png",
"128": "images/128x128_light.png"
},
"default_title": "YouTrack Timer",
"default_popup": "index.html"
},
"permissions": [
"storage"
],
"optional_host_permissions": [
"https://*/*"
],
"background": {
"service_worker": "background.js"
}
}
16 changes: 16 additions & 0 deletions scripts/update-manifest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const fs = require("fs");
const path = require("path");

const package = path.join(__dirname, "../package.json");
const manifest = path.join(__dirname, "../public/manifest.json");

const packageJson = require(package);
const manifestJson = require(manifest);

manifestJson.version = packageJson.version;

const json = JSON.stringify(manifestJson, null, 4);

fs.writeFileSync(manifest, json);

console.log("Updated manifest.json with version from package.json");
138 changes: 138 additions & 0 deletions src/Store.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@


class Store {

static types = {
BACKGROUND: 'BACKGROUND',
POPUP: 'POPUP',
WEB: 'WEB',
CONTENT: 'CONTENT'
}

static getType() {
if (chrome && chrome.extension && chrome.extension.getBackgroundPage && chrome.extension.getBackgroundPage() === window) return this.types.BACKGROUND;
else if (chrome && chrome.extension && chrome.extension.getBackgroundPage && chrome.extension.getBackgroundPage() !== window) return this.types.POPUP;
else if (!chrome || !chrome.runtime || !chrome.runtime.onMessage) return this.types.WEB;
else return this.types.CONTENT;
}

static getInstance() {
switch (this.getType()) {
case this.types.BACKGROUND:
return new ChromeExtensionStore();
case this.types.POPUP:
return new ChromeExtensionStore();
case this.types.WEB:
return new WebStore();
case this.types.CONTENT:
return new WebStore();
default:
throw new Error('Unknown store type');
}
}


constructor() {
this.isConfigured = false;
this.baseUrl = null;
this.token = null;
this.userUrl = null;
}

async load() { throw new Error('Not implemented') }
async save() { throw new Error('Not implemented') }
async clear() { throw new Error('Not implemented') }
}


class ChromeExtensionStore extends Store {
constructor() { super() }

async load() {
return new Promise((resolve, reject) => {
chrome.storage.sync.get(['isConfigured', 'baseUrl', 'userUrl', 'token'], (result) => {
if (chrome.runtime.lastError) {
reject(chrome.runtime.lastError);
} else {
this.isConfigured = result.isConfigured;
this.baseUrl = result.baseUrl;
this.userUrl = result.userUrl;
this.token = result.token;
resolve(result);
}
});
});
}

async save() {
return new Promise((resolve, reject) => {
chrome.storage.sync.set({
isConfigured: this.isConfigured,
baseUrl: this.baseUrl,
userUrl: this.userUrl,
token: this.token
}, () => {
if (chrome.runtime.lastError) {
reject(chrome.runtime.lastError);
} else {
resolve();
}
});
});
}

async clear() {
return new Promise((resolve, reject) => {
chrome.storage.sync.clear(() => {
if (chrome.runtime.lastError) {
reject(chrome.runtime.lastError);
} else {
resolve();
}
});
});
}
}


class WebStore extends Store {
constructor() { super() }

async load() {
return new Promise((resolve) => {
const isConfigured = localStorage.getItem('isConfigured');
const baseUrl = localStorage.getItem('baseUrl');
const userUrl = localStorage.getItem('userUrl');
const token = localStorage.getItem('token');

this.isConfigured = isConfigured;
this.baseUrl = baseUrl;
this.userUrl = userUrl;
this.token = token;

resolve({ isConfigured, baseUrl, userUrl, token });
});
}

async save() {
return new Promise((resolve) => {
localStorage.setItem('isConfigured', this.isConfigured);
localStorage.setItem('baseUrl', this.baseUrl);
localStorage.setItem('userUrl', this.userUrl);
localStorage.setItem('token', this.token);
resolve();
});
}

async clear() {
return new Promise((resolve) => {
localStorage.removeItem('isConfigured');
localStorage.removeItem('baseUrl');
localStorage.removeItem('userUrl');
localStorage.removeItem('token');
resolve();
});
}
}

export default Store;
Loading

0 comments on commit 657aebb

Please sign in to comment.