Skip to content

Commit eb7480e

Browse files
authored
Merge pull request #26 from mlsof21/prevent-other-tabs
Prevent other tabs
2 parents 4a15c50 + 19b8119 commit eb7480e

File tree

9 files changed

+198
-111
lines changed

9 files changed

+198
-111
lines changed

CHANGELOG.md

Lines changed: 58 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,58 @@
1-
### 1.2.0 - 2022-09-24 - Always Listening
2-
3-
- Added a toggle-able `Always Listening` mode
4-
- Each command must be prefixed with an activation phrase (defaulted to `okay ghost`)
5-
- Added fix for `maxPower` command (didn't work in normal DIM, only in beta)
6-
- Added fix for search already being populated when performing a command.
7-
8-
### 1.1.3 - 2022-09-20 - Perk fix
9-
10-
- Fixed perk matching
11-
12-
### 1.1.2 - 2022-09-19 - Options page links
13-
14-
- Added an `onInstalled` event for the extension. It'll direct users to the options page.
15-
- Link to the options page from the `?`
16-
17-
### 1.1.1 - 2022-09-16 - Better performance
18-
19-
- Use a `waitForElement/waitForSearchToUpdate` function instead of arbitrarily sleeping in code
20-
- Results in at least a 300% improvement in action duration
21-
22-
### 1.1.0 - 2022-09-13 - The One with Custom Commands
23-
24-
- Quite a few changes in this one
25-
- Reworked how the extension waits for the search to update visible (not dimmed) items
26-
- Really reworked how all UI interactions are performed
27-
- Added the ability to customize the command words for particular actions
28-
- Visit the options page (click the extension icon) to set these
29-
- Added a `store` command for storing items in the vault
30-
- Added an `equip` command for directly equipping an item on your current character (when possible)
31-
- This works like how `transfer` previously did, and `transfer` has been updated to only transfer, not equip
32-
- (from above) `Transfer` now only transfers instead of equipping
33-
- Added mic icon on page with a link to the website
34-
- When listening, there will be text next to the icon that updates as the user speaks their command
35-
- Added link to the [Voice DIM website](https://www.voicedim.com) via the `?` icon.
36-
- Fixed `Start Farming mode` command if a user has at least 10 loadouts saved
37-
38-
### 1.0.1 - 2022-08-23 - Corrected Shortcut
39-
40-
- Defaulted the shortcut correctly (set to `Ctrl+Shift+0`)
41-
42-
### 1.0.0 - 2022-08-19 - Initial Release
43-
44-
- See [Reddit post](https://www.reddit.com/r/DestinyTheGame/comments/wseigx/interact_with_dim_using_your_voice/) about the available commands with more info
45-
- Commands are available to:
46-
- Transfer a weapon by name
47-
- Transfer a weapon with particular perks
48-
- Transfer a weapon by attribute (energy type, slot, ammo type, etc)
49-
- Collect from the postmaster
50-
- Start/Stop farming mode
51-
- Equip loadouts by name
52-
- Equip max power
53-
- Use global shortcut to activate listening
1+
### 1.2.1 - 2022-10-03 - Only in Inventory
2+
3+
- Added fix for loading DIM on another tab. Previously required reloading the page on the inventory tab. Now Voice DIM will load no matter what page is started on
4+
- Added fix for a user having the item popup sidebar being collapsed.
5+
6+
### 1.2.0 - 2022-09-24 - Always Listening
7+
8+
- Added a toggle-able `Always Listening` mode
9+
- Each command must be prefixed with an activation phrase (defaulted to `okay ghost`)
10+
- Added fix for `maxPower` command (didn't work in normal DIM, only in beta)
11+
- Added fix for search already being populated when performing a command.
12+
13+
### 1.1.3 - 2022-09-20 - Perk fix
14+
15+
- Fixed perk matching
16+
17+
### 1.1.2 - 2022-09-19 - Options page links
18+
19+
- Added an `onInstalled` event for the extension. It'll direct users to the options page.
20+
- Link to the options page from the `?`
21+
22+
### 1.1.1 - 2022-09-16 - Better performance
23+
24+
- Use a `waitForElement/waitForSearchToUpdate` function instead of arbitrarily sleeping in code
25+
- Results in at least a 300% improvement in action duration
26+
27+
### 1.1.0 - 2022-09-13 - The One with Custom Commands
28+
29+
- Quite a few changes in this one
30+
- Reworked how the extension waits for the search to update visible (not dimmed) items
31+
- Really reworked how all UI interactions are performed
32+
- Added the ability to customize the command words for particular actions
33+
- Visit the options page (click the extension icon) to set these
34+
- Added a `store` command for storing items in the vault
35+
- Added an `equip` command for directly equipping an item on your current character (when possible)
36+
- This works like how `transfer` previously did, and `transfer` has been updated to only transfer, not equip
37+
- (from above) `Transfer` now only transfers instead of equipping
38+
- Added mic icon on page with a link to the website
39+
- When listening, there will be text next to the icon that updates as the user speaks their command
40+
- Added link to the [Voice DIM website](https://www.voicedim.com) via the `?` icon.
41+
- Fixed `Start Farming mode` command if a user has at least 10 loadouts saved
42+
43+
### 1.0.1 - 2022-08-23 - Corrected Shortcut
44+
45+
- Defaulted the shortcut correctly (set to `Ctrl+Shift+0`)
46+
47+
### 1.0.0 - 2022-08-19 - Initial Release
48+
49+
- See [Reddit post](https://www.reddit.com/r/DestinyTheGame/comments/wseigx/interact_with_dim_using_your_voice/) about the available commands with more info
50+
- Commands are available to:
51+
- Transfer a weapon by name
52+
- Transfer a weapon with particular perks
53+
- Transfer a weapon by attribute (energy type, slot, ammo type, etc)
54+
- Collect from the postmaster
55+
- Start/Stop farming mode
56+
- Equip loadouts by name
57+
- Equip max power
58+
- Use global shortcut to activate listening

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
{
22
"name": "voice-dim",
3-
"version": "1.2.0",
3+
"version": "1.2.1",
44
"description": "Perform common DIM actions by using speech recognition.",
55
"main": "dist/chrome/js/voice-dim.js",
66
"scripts": {
77
"test": "echo \"Error: no test specified\" && exit 1",
88
"zip": "npm run build && python scripts/build.py",
99
"build": "rimraf dist/ && webpack --env mode=production --config webpack.config.js",
10-
"watch": "webpack --env mode=development --config webpack.config.js --progress --watch"
10+
"watch": "webpack --env mode=development --config webpack.config.js --progress --watch",
11+
"update-version": "python scripts/update_version.py"
1112
},
1213
"repository": {
1314
"type": "git",
@@ -45,4 +46,4 @@
4546
"webpack-cli": "^4.10.0",
4647
"webpack-visualizer-plugin2": "^1.0.0"
4748
}
48-
}
49+
}

public/manifest.chrome.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
{
22
"name": "Voice DIM",
33
"description": "Control DIM with your voice.",
4-
"version": "1.2.0",
4+
"version": "1.2.1",
55
"manifest_version": 3,
66
"background": {
77
"service_worker": "js/background.js"
88
},
99
"content_scripts": [
1010
{
11-
"matches": ["https://*.destinyitemmanager.com/*inventory"],
11+
"matches": ["https://*.destinyitemmanager.com/*"],
1212
"js": ["js/voiceDim.js"],
1313
"css": ["css/voiceDim.css"]
1414
}

public/manifest.firefox.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "Voice DIM",
33
"description": "Control DIM with your voice.",
4-
"version": "1.2.0",
4+
"version": "1.2.1",
55
"manifest_version": 2,
66
"background": {
77
"scripts": ["js/background.js"]

scripts/update_version.py

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from datetime import datetime
12
import getopt
23
import json
34
import os
@@ -37,31 +38,54 @@ def get_next_version(current_version: str, part_to_update: str):
3738
return f"{major_version}.{minor_version}.{bugfix_version}"
3839

3940

40-
def write_new_version(file_path, new_version):
41+
def write_new_version(file_path: str, new_version: str, dry_run: bool = False):
4142
with open(file_path, 'r') as f:
4243
data = json.load(f)
4344

4445
data['version'] = f"{new_version}"
4546

47+
if dry_run:
48+
return
49+
4650
with open(file_path, 'w') as f:
47-
json.dump(data, f, indent=4)
51+
json.dump(data, f, indent=2)
52+
53+
54+
def write_changelog_update(file_path: str, new_version: str, dry_run: bool = False):
55+
with open(file_path, 'r') as f:
56+
data = f.read()
57+
58+
if data.find(new_version) < 0:
59+
now = datetime.now()
60+
date = now.strftime('%Y-%m-%d')
61+
62+
data = f"### {new_version} - {date} - <title>\n\n- <insert changes>\n\n{data}"
63+
print(data)
64+
65+
if dry_run:
66+
return
67+
68+
with open(file_path, 'w') as f:
69+
f.write(data)
4870

4971

5072
def main():
5173
argument_list = sys.argv[1:]
52-
options = 'p:'
53-
long_options = "part="
74+
options = 'dp:'
75+
long_options = ["dry-run", "part="]
5476
# Parsing argument
5577
arguments, values = getopt.getopt(argument_list, options, long_options)
5678
part = 'bugfix'
79+
dry_run = False
5780
# checking each argument
5881
for current_arg, current_value in arguments:
59-
6082
if current_arg in ("-p", "--part"):
6183
if current_value in ('major', 'minor', 'bugfix'):
6284
part = current_value
6385
else:
6486
print("No part provided. Updating the bugfix version by default")
87+
if current_arg in ('-d', '--dry-run'):
88+
dry_run = True
6589

6690
git_root = get_git_root(os.getcwd())
6791
files = [git_root + '/public/manifest.chrome.json', git_root +
@@ -86,7 +110,9 @@ def main():
86110
print(next_version)
87111

88112
for file in files:
89-
write_new_version(file, next_version)
113+
write_new_version(file, next_version, dry_run)
114+
115+
write_changelog_update(git_root+"/CHANGELOG.md", next_version, dry_run)
90116

91117

92118
if __name__ == "__main__":

src/ts/background.ts

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,36 @@ import { infoLog } from './common';
22

33
chrome.commands.onCommand.addListener((command: any) => {
44
infoLog('voice dim', `Command "${command}" triggered`);
5+
sendDimTabMessage({ dimShortcutPressed: true });
6+
});
57

6-
chrome.tabs.query({}, (tabs: any[]) => {
7-
const dimTabs = tabs.filter((tab: { url: string }) => tab.url?.match(/destinyitemmanager\.com.*inventory/));
8-
9-
if (dimTabs && dimTabs[0]?.id)
10-
chrome.tabs.sendMessage(dimTabs[0].id, { dimShortcutPressed: true }, (response: any) => {
11-
infoLog('voice dim', { response });
12-
});
13-
});
8+
chrome.tabs.onUpdated.addListener(async function (tabId, changeInfo, tab) {
9+
const dimTabId = await getDimTabId();
10+
if (dimTabId && tabId === dimTabId) {
11+
if (changeInfo.url && !changeInfo.url.includes('inventory')) {
12+
sendDimTabMessage('not on inventory page');
13+
} else if (changeInfo.url && changeInfo.url.includes('inventory')) {
14+
sendDimTabMessage('on inventory page');
15+
}
16+
}
1417
});
1518

16-
chrome.runtime.onMessage.addListener((data: any) => {
19+
async function getDimTabId(): Promise<number | undefined | null> {
20+
const dimTabs = await chrome.tabs.query({ url: 'https://*.destinyitemmanager.com/*' });
21+
return dimTabs && dimTabs.length >= 1 ? dimTabs[0]?.id : null;
22+
}
23+
async function sendDimTabMessage(message: any) {
24+
const dimTabId = await getDimTabId();
25+
if (dimTabId) {
26+
infoLog('message', 'sending', message);
27+
28+
chrome.tabs.sendMessage(dimTabId, message, (response: any) => {
29+
infoLog('voice dim', { response });
30+
});
31+
}
32+
}
33+
34+
chrome.runtime.onMessage.addListener((data: any, sender: chrome.runtime.MessageSender) => {
1735
infoLog('voice dim', { data });
1836
if (data === 'showOptions') {
1937
openOptionsPage();

src/ts/common.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
export interface Action {
2-
func: () => void;
3-
timeout: number;
4-
}
5-
61
export function infoLog(tag: string, message: unknown, ...args: unknown[]) {
72
console.log(`[${tag}]`, message, ...args);
83
}
94

5+
export function debugLog(tag: string, message: unknown, ...args: unknown[]) {
6+
console.debug(`[${tag}]`, message, ...args);
7+
}
8+
109
export const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
1110

1211
export const debounce = <F extends (...args: Parameters<F>) => ReturnType<F>>(func: F, waitFor: number = 300) => {
@@ -54,16 +53,16 @@ export async function waitForElementToDisplay(
5453
checkFrequencyInMs: number = 50,
5554
timeoutInMs: number = 2000
5655
): Promise<Element | null> {
57-
return new Promise((resolve) => {
56+
return new Promise((resolve, reject) => {
5857
var startTimeInMs = Date.now();
5958
(function loopSearch() {
6059
if (document.querySelector(selector) != null) {
6160
return resolve(document.querySelector(selector));
6261
} else {
6362
setTimeout(function () {
6463
if (timeoutInMs && Date.now() - startTimeInMs > timeoutInMs) {
65-
infoLog('voice dim', "couldn't find", selector);
66-
return;
64+
debugLog('voice dim', "couldn't find", selector);
65+
return reject();
6766
}
6867
loopSearch();
6968
}, checkFrequencyInMs);
@@ -93,13 +92,13 @@ export const DEFAULT_ALWAYS_LISTENING: AlwaysListening = {
9392
activationPhrase: 'okay ghost',
9493
};
9594

96-
export function store(key: string, value: any) {
95+
export function store<T>(key: string, value: T) {
9796
chrome.storage.local.set({ [key]: value }, () => {
9897
infoLog('voice dim', 'Stored', key, value);
9998
});
10099
}
101100

102-
export function retrieve(key: string, defaultValue: any): Promise<any> {
101+
export function retrieve<T>(key: string, defaultValue: T): Promise<T> {
103102
return new Promise((resolve, reject) => {
104103
chrome.storage.local.get([key], function (result) {
105104
if (chrome.runtime.lastError) {

src/ts/options.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ function onCommandChange() {
1313
Object.keys(DEFAULT_COMMANDS).forEach((command) => {
1414
commands[command] = getTextValueById(command);
1515
});
16-
store('commands', commands);
16+
store<Record<string, string[]>>('commands', commands);
1717

1818
updateSaveText(true, 'Saved!');
1919
setTimeout(() => updateSaveText(false), 3000);
@@ -46,7 +46,10 @@ function onActivationPhraseChange() {
4646
updateSaveText(true, 'Saved!');
4747
setTimeout(() => updateSaveText(false), 3000);
4848

49-
store('alwaysListening', { active: listeningToggle.checked, activationPhrase: activationPhrase.value });
49+
store<AlwaysListening>('alwaysListening', {
50+
active: listeningToggle.checked,
51+
activationPhrase: activationPhrase.value,
52+
});
5053
sendListenOptionsMessage();
5154
}
5255

@@ -56,7 +59,10 @@ function onAlwaysListeningChange(listeningOptions: AlwaysListening) {
5659
updateSaveText(true, 'Saved!');
5760
setTimeout(() => updateSaveText(false), 3000);
5861

59-
store('alwaysListening', { active: listeningOptions.active, activationPhrase: listeningOptions.activationPhrase });
62+
store<AlwaysListening>('alwaysListening', {
63+
active: listeningOptions.active,
64+
activationPhrase: listeningOptions.activationPhrase,
65+
});
6066
sendListenOptionsMessage();
6167
}
6268

0 commit comments

Comments
 (0)