Skip to content
This repository has been archived by the owner on Aug 18, 2023. It is now read-only.

Commit

Permalink
Add support for Firefox (#142)
Browse files Browse the repository at this point in the history
* 🔧 use chrome.storage.local if on Firefox

* 🔧 add a manifest file for Firefox

* 🐛 make the download GIF feature work in Firefox

* ✨

* 🔧 remove unsupported tabs.update options so it works in Firefox

* 🔧 actually require tabs permissions

* 🐛 fix firefox's manifest

* 📦

* 📦

* 📦 use config w/ pack.js

* 📦 add npm scripts to build chrome/firefox versions

* 📦 add web-ext as dep

* 📦 rename pack:chrome-opera to pack:chrome

* 📒

* 📦 try yarn on travis
  • Loading branch information
eramdam committed Apr 30, 2017
1 parent ac5a6d6 commit 99e4c1b
Show file tree
Hide file tree
Showing 14 changed files with 7,778 additions and 40 deletions.
6 changes: 1 addition & 5 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ reverse/
config/*.js
events.js
backup

*.crx

*.nex

*.zip
yarn.lock
*.zip
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
language: node_js
cache: yarn
node_js:
- "node"
File renamed without changes.
2 changes: 2 additions & 0 deletions config/default.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
module.exports = {
FirefoxId: '',
opera_key: '',
'Client': {
'debug': false,
'remote_inst': true,
Expand Down
17 changes: 15 additions & 2 deletions gulpfile.babel.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import source from 'vinyl-source-stream';
import buffer from 'vinyl-buffer';
import eslint from 'gulp-eslint';
import uglify from 'gulp-uglify';
import zip from 'gulp-zip';
import sourcemaps from 'gulp-sourcemaps';
import gutil from 'gulp-util';

Expand Down Expand Up @@ -78,11 +79,23 @@ const buildWithBrowserify = (entry) => {
/*
*
* `gulp clean`
* Remove the build/ folder (used before build)
* Remove the dist/ folder (used before build)
*
*/
gulp.task('clean', () => del(['dist/']));

/*
*
* `gulp zip`
* zips the dist/ folder (used before build)
*
*/
gulp.task('zip', () => (
gulp.src('dist/*')
.pipe(zip(`dist-${browser}.zip`))
.pipe(gulp.dest('artifacts/'))
));

/*
*
* `gulp static`
Expand Down Expand Up @@ -165,7 +178,7 @@ gulp.task('lint', () => (
*
*/
gulp.task('build', (done) => {
const tasks = ['clean', 'manifest', ['js', 'static', 'css', 'css-options'], 'static-news'];
const tasks = ['clean', 'manifest', ['js', 'static', 'css', 'css-options'], 'static-news', 'zip'];

if (!config.get('Client.remote_inst'))
tasks.push('embed_instagram');
Expand Down
12 changes: 9 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,13 @@
"scripts": {
"start": "cross-env NODE_ENV=dev gulp",
"build": "cross-env NODE_ENV=dev gulp build",
"build:prod": "rimraf dist/ && cross-env NODE_ENV=prod gulp build --type production && bestzip packed/dist.zip dist/",
"pack": "node tools/pack.js",
"release": "npm run build:prod && npm run pack",
"chrome": "cross-env NODE_ENV=prod gulp build --browser chrome",
"chrome:prod": "cross-env NODE_ENV=prod gulp build --type production --browser chrome",
"firefox": "cross-env NODE_ENV=prod gulp build --browser firefox",
"firefox:prod": "cross-env NODE_ENV=prod gulp build --type production --browser firefox",
"pack:chrome": "node tools/pack.js",
"pack:firefox": "web-ext build -s dist -a artifacts",
"release": "npm run chrome:prod && npm run pack:chrome && npm run firefox:prod && npm run pack:firefox",
"test": "gulp lint && npm run release"
},
"homepage": "https://github.com/eramdam/BetterTweetDeck",
Expand Down Expand Up @@ -51,6 +55,7 @@
"gulp-sourcemaps": "^1.6.0",
"gulp-uglify": "^1.5.1",
"gulp-util": "^3.0.7",
"gulp-zip": "^4.0.0",
"jquery": "^3.0.0",
"js-emoji": "https://github.com/iamcal/js-emoji/tarball/v3.0.2",
"lodash": "^4.0.0",
Expand All @@ -71,6 +76,7 @@
"vinyl-buffer": "^1.0.0",
"vinyl-source-stream": ">=1.1.0",
"vinyl-transform": "^1.0.0",
"web-ext": "^1.9.0",
"xml-js": "^1.0.0"
}
}
10 changes: 7 additions & 3 deletions src/js/background.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@

import gifshot from 'gifshot';
import * as BHelper from './util/browserHelper';
import * as Messages from './util/messaging';
import * as Log from './util/logger';
Expand Down Expand Up @@ -93,9 +93,7 @@ function contextMenuHandler(info, tab, settings) {
focused: true,
}, () => {
chrome.tabs.update(TDTab.id, {
selected: true,
active: true,
highlighted: true,
}, () => {
chrome.tabs.sendMessage(TDTab.id, {
text: textToShare,
Expand Down Expand Up @@ -160,6 +158,12 @@ Messages.on((message, sender, sendResponse) => {
BHelper.settings.get(message.key, (val) => sendResponse({ val }));
return true;

case 'download_gif':
gifshot.createGIF(message.options, obj => {
sendResponse({ obj });
});
return true;

default:
return false;
}
Expand Down
52 changes: 38 additions & 14 deletions src/js/content.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import * as Thumbnails from './util/thumbnails';
import * as Templates from './util/templates';
import * as Usernames from './util/usernames';
import * as Emojis from './util/emojis';
import * as Log from './util/logger.js';
import * as Log from './util/logger';
import * as BHelper from './util/browserHelper';

import { $, TIMESTAMP_INTERVAL, on, sendEvent } from './util/util';

Expand Down Expand Up @@ -41,6 +42,16 @@ sendMessage({ action: 'get_settings' }, (response) => {
});
});

function saveGif(gifshotObj, name, event) {
return fetch(gifshotObj.image)
.then(res => res.blob())
.then(blob => {
event.target.style.opacity = 1;
event.target.innerText = 'Download as .GIF';
FileSaver.saveAs(blob, `${name}.gif`);
});
}


/**
* Since this function wil be called every ~3sec we have to check if we actually
Expand Down Expand Up @@ -608,31 +619,44 @@ on('BTDC_gotMediaGalleryChirpHTML', (ev, data) => {
e.preventDefault();
e.target.style.opacity = 0.8;

gifshot.createGIF({
const gifshotOptions = {
gifWidth: videoEl.getAttribute('data-btd-width'),
gifHeight: videoEl.getAttribute('data-btd-height'),
video: [videoEl.getAttribute('src')],
name: videoEl.getAttribute('data-btd-name'),
numFrames: Math.floor(videoEl.duration / 0.1),
sampleInterval: 10,
};

const gifshotCb = (obj) => {
if (obj.error) {
return;
}

saveGif(obj, gifshotOptions.name, e);
};

// Firefox doesn't support Web Workers from content scripts so we have to run it in the background
// ...
// ...
// Yes, it's hacky but we have no choice ¯\(ツ)/¯
if (BHelper.isFirefox) {
e.target.innerText = 'Converting to GIF... (in progress)';
return sendMessage({
action: 'download_gif',
options: gifshotOptions,
}, (response) => gifshotCb(response.obj));
}

return gifshot.createGIF(Object.assign(gifshotOptions, {
progressCallback: (progress) => {
if (progress > 0.99) {
e.target.innerText = 'Converting to GIF... (Finalizing)';
} else {
e.target.innerText = `Converting to GIF... (${Number(progress * 100).toFixed(1)}%)`;
}
},
}, obj => {
if (!obj.error) {
e.target.innerText = 'Preparing the file...';
fetch(obj.image)
.then(res => res.blob())
.then(blob => {
e.target.style.opacity = 1;
e.target.innerText = 'Download as .GIF';
FileSaver.saveAs(blob, `${videoEl.getAttribute('data-btd-name')}.gif`);
});
}
});
}), gifshotCb);
});
}
});
Expand Down
7 changes: 5 additions & 2 deletions src/js/util/browserHelper.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
const fs = require('fs');
const packageJson = JSON.parse(fs.readFileSync(`${__dirname}/../../../package.json`, 'utf8'));

export const getUA = () => window.navigator.userAgent;

// From https://github.com/lorenwest/node-config/blob/master/lib/config.js#L131-L152
const getKey = (object, property) => {
const elems = Array.isArray(property) ? property : property.split('.');
Expand All @@ -18,10 +20,11 @@ const getKey = (object, property) => {
return getKey(value, elems.slice(1));
};

const storage = chrome.storage.sync || chrome.storage.local;
export const isFirefox = getUA().includes('Firefox/');
const storage = isFirefox ? chrome.storage.local : chrome.storage.sync;

export const getVersion = () => packageJson.version;
export const getUA = () => window.navigator.userAgent;

export const getMessage = (msg) => {
const string = chrome.i18n.getMessage(msg);

Expand Down
17 changes: 10 additions & 7 deletions tools/manifests/common.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const fs = require('fs');
const packageJson = JSON.parse(fs.readFileSync(`${__dirname}/../../package.json`, 'utf8'));

/* eslint quotes: 0 */
module.exports = {
name: 'Better TweetDeck 3',
short_name: 'BetterTDeck',
Expand Down Expand Up @@ -44,21 +45,23 @@ module.exports = {
'*://tweetdeck.twitter.com/*',
'contextMenus',
'notifications',
'tabs',
],
options_ui: {
page: 'options/ui/ui.html',
chrome_style: false,
},
web_accessible_resources: [
'js/inject.js',
'js/content.js.map',
'js/inject.js.map',
'js/background.js.map',
'emojis/sheet_twitter_64.png',
'embeds.js',
'emojis/emoji-happy.svg',
'emojis/sheet_twitter_64.png',
'icons/controller-play.svg',
'js/background.js.map',
'js/content.js.map',
'js/inject.js',
'js/inject.js.map',
'options/options.html',
'options/options.html',
'embeds.js',
],
content_security_policy: 'img-src \'self\' *; default-src; connect-src * https:; style-src \'unsafe-inline\'',
content_security_policy: `img-src https: data: 'self' *; default-src; connect-src * https:; style-src 'unsafe-inline'`,
};
3 changes: 3 additions & 0 deletions tools/manifests/edge.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/**
* EDGE SUPPORT STILL IN WORK THO
*/
const common = require('./common.js');

module.exports = {
Expand Down
15 changes: 15 additions & 0 deletions tools/manifests/firefox.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const config = require('config');

/* eslint quotes: 0 */
module.exports = Object.assign(require('./common.js'), {
name: '__MSG_appName__',
description: '__MSG_appDesc__',
default_locale: 'en',
applications: {
gecko: {
id: config.get('FirefoxId'),
strict_min_version: '48.0',
},
},
content_security_policy: `img-src https: data: 'self' *; media-src * https:; connect-src * https:; style-src 'unsafe-inline'; object-src 'self'; script-src 'self';`,
});
9 changes: 5 additions & 4 deletions tools/pack.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
const chalk = require('chalk');
const config = require('config');
const clog = (color, ...args) => console.log(chalk[color](...args));
const fs = require('fs');
const path = require('path');

if (!process.argv[2]) {
if (!config.get('opera_key')) {
clog('red', 'Please provide a private key file');
process.exit();
}

const privateKeyPath = path.resolve(process.argv[2]);
const privateKeyPath = path.resolve(config.get('opera_key'));
const extensionPath = path.resolve(__dirname, '../dist');
const ChromeExtension = require('crx');
const crx = new ChromeExtension({
Expand All @@ -23,14 +24,14 @@ crx.load(extensionPath)
clog('blue', 'Loaded', d.manifest.short_name, d.manifest.version);

return crx.pack().then(buffer => {
fs.writeFile(path.resolve(__dirname, '../packed/', 'better-tweetdeck.crx'), buffer, (err) => {
fs.writeFile(path.resolve(__dirname, '../artifacts/', 'better-tweetdeck.crx'), buffer, (err) => {
if (err) {
clog('red', err);
}

clog('green', 'Saved better-tweetdeck.crx');
});
fs.writeFile(path.resolve(__dirname, '../packed/', 'better-tweetdeck.nex'), buffer, (err) => {
fs.writeFile(path.resolve(__dirname, '../artifacts/', 'better-tweetdeck.nex'), buffer, (err) => {
if (err) {
clog('red', err);
}
Expand Down
Loading

0 comments on commit 99e4c1b

Please sign in to comment.