Skip to content

Commit 91e9208

Browse files
authored
Merge pull request #22 from codebridger/dev
Improve login tests and optimize CI workflow to prevent duplicate runs
2 parents d0d029d + 5301d6a commit 91e9208

11 files changed

Lines changed: 340 additions & 157 deletions

File tree

.github/workflows/release.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ concurrency:
2222
jobs:
2323
verify:
2424
name: Verify (lint, unit, build, e2e)
25+
# Prevent duplicate runs on internal PRs from branches that already trigger a push event
26+
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository || !contains(fromJSON('["main", "dev"]'), github.event.pull_request.head.ref)
2527
runs-on: ubuntu-latest
2628
steps:
2729
- name: Checkout

CHANGELOG-DEV.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
## [1.11.1-dev.1](https://github.com/codebridger/subturtle-extension-apps/compare/v1.11.0...v1.11.1-dev.1) (2026-05-06)
2+
3+
4+
### Bug Fixes
5+
6+
* [#86](https://github.com/codebridger/subturtle-extension-apps/issues/86)exgqfpu skip token writes to host LS on dashboard origins ([838451e](https://github.com/codebridger/subturtle-extension-apps/commit/838451e9ad10d3a3755691b4ca586a0d3815a008)), closes [#86exgqfpu](https://github.com/codebridger/subturtle-extension-apps/issues/86exgqfpu)
7+
18
# [1.11.0-dev.4](https://github.com/codebridger/subturtle-extension-apps/compare/v1.11.0-dev.3...v1.11.0-dev.4) (2026-05-06)
29

310

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "subturtle-extension",
3-
"version": "1.11.1",
3+
"version": "1.11.1-dev.1",
44
"private": true,
55
"scripts": {
66
"dev": "webpack --watch",
@@ -60,4 +60,4 @@
6060
"vue": "3.5.17",
6161
"vue-router": "4.5.1"
6262
}
63-
}
63+
}

src/common/helper/log.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
1-
export function log(...arg) {
2-
console.log("Subturtle:", ...arg);
1+
export function log(...arg: any[]) {
2+
console.log("[Subturtle]", ...arg);
33
}
44

5-
export function error(...arg) {
6-
console.error("Subturtle:", ...arg);
5+
export function warn(...arg: any[]) {
6+
console.warn("[Subturtle]", ...arg);
7+
}
8+
9+
export function debug(...arg: any[]) {
10+
if (process.env.NODE_ENV !== "production") {
11+
console.debug("[Subturtle]", ...arg);
12+
}
13+
}
14+
15+
export function error(...arg: any[]) {
16+
console.error("[Subturtle]", ...arg);
717
}

src/common/helper/massage.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { BaseMessage, LoginStatusResponse } from "../types/messaging";
2+
import { debug, log } from "./log";
23

34
/**
45
* Send message to background
@@ -10,6 +11,7 @@ export async function sendMessage<T extends BaseMessage | LoginStatusResponse>(
1011
) {
1112
return new Promise<T>((resolve, reject) => {
1213
try {
14+
debug("Sending message to background:", message);
1315
chrome.runtime.sendMessage(message, (response) => {
1416
if (chrome.runtime.lastError) {
1517
// Chrome runtime errors should be properly formatted with message
@@ -22,6 +24,7 @@ export async function sendMessage<T extends BaseMessage | LoginStatusResponse>(
2224
// Handle case where response is undefined/null
2325
reject(new Error("No response received"));
2426
} else {
27+
debug("Received response:", response);
2528
resolve(response);
2629
}
2730
});

src/common/types/messaging.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ export type SettingsObject = {
2020
export class BaseMessage {
2121
type!: string;
2222

23-
static is(message: any) {}
24-
static checkResponse(response: any) {}
23+
static is(message: any) { }
24+
static checkResponse(response: any) { }
2525
}
2626

2727
export class GetLoginStatusMessage implements BaseMessage {
@@ -35,6 +35,9 @@ export class GetLoginStatusMessage implements BaseMessage {
3535
return message.type === MESSAGE_TYPE.GET_LOGIN_STATUS;
3636
}
3737

38+
/**
39+
* To check if the message has an expected token in response.
40+
*/
3841
static checkResponse(response: any): response is LoginStatusResponse {
3942
return response && response.status && response.token;
4043
}

src/plugins/modular-rest.ts

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ import {
4949
import { ref } from "vue";
5050
import { useProfileStore } from "../stores/profile";
5151
import { analytic } from "./mixpanel";
52+
import { debug, error, log } from "../common/helper/log";
5253

5354
GlobalOptions.set({
5455
host: process.env.SUBTURTLE_API_URL || "",
@@ -61,6 +62,7 @@ export {
6162
} from "@modular-rest/client";
6263

6364
export const isLogin = ref(false);
65+
6466
function updateIsLogin() {
6567
const loginInfo =
6668
authentication.isLogin && authentication.user?.type.toLowerCase() == "user";
@@ -79,8 +81,8 @@ function updateIsLogin() {
7981

8082
return true;
8183
})
82-
.catch((error) => {
83-
console.error("Error bootstrapping profile store:", error);
84+
.catch((errorDetail) => {
85+
error("Error bootstrapping profile store:", errorDetail);
8486
return false;
8587
});
8688
}
@@ -111,11 +113,20 @@ export async function loginWithLastSession() {
111113

112114
const user = await authentication.loginWithToken(
113115
res.token as string,
114-
true
116+
// token will be stored on background service, so we don't need to store it here
117+
false
115118
);
116-
return user;
119+
120+
debug("retrieved user from last login: ", user);
121+
122+
if (user.type == "anonymous") {
123+
authentication.logout();
124+
return false;
125+
} else {
126+
return updateIsLogin();
127+
}
128+
117129
})
118-
.then((_user) => updateIsLogin())
119130
.then(async (_isRegisteredUser) => {
120131
// updateIsLogin's truthy result means "registered user with a real
121132
// account". Anonymous users return false here even though they hold a
@@ -126,19 +137,20 @@ export async function loginWithLastSession() {
126137
// session, clearing chrome.storage.sync and broadcasting null to every
127138
// tab — and the next translate from any content script then 412s
128139
// because its Authorization header is empty.
129-
if (!authentication.isLogin) {
140+
if (!_isRegisteredUser && !authentication.isLogin) {
130141
await logout();
131142
return false;
132143
}
133144
return true;
134145
})
135-
136146
.finally(() => {
137147
if (!authentication.isLogin) {
148+
debug("Login with last session failed, trying anonymous login");
149+
138150
authentication
139151
.loginAsAnonymous()
140152
.then(async () => {
141-
console.log(
153+
debug(
142154
"Subturtle Anonymous login succeded",
143155
authentication.isLogin
144156
);
@@ -153,14 +165,14 @@ export async function loginWithLastSession() {
153165
try {
154166
await sendMessage(new StoreUserTokenMessage(token));
155167
} catch (err) {
156-
console.warn(
168+
error(
157169
"Subturtle: persisting anonymous token to background failed",
158170
err
159171
);
160172
}
161-
if (typeof localStorage !== "undefined") {
162-
localStorage.setItem("token", token);
163-
}
173+
// if (typeof localStorage !== "undefined") {
174+
// localStorage.setItem("token", token);
175+
// }
164176
}
165177
updateIsLogin();
166178
})

src/trusted-types-polyfill.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@
1717
* when the extension needs to run on a host that blocks Vue's policy.
1818
*/
1919

20+
import { debug } from "./common/helper/log";
21+
2022
const trustedTypes = (window as any).trustedTypes;
2123

2224
if (trustedTypes && trustedTypes.createPolicy) {
23-
console.log("[Subturtle] Setting up Trusted Types workaround");
25+
debug("[Subturtle] Setting up Trusted Types workaround");
2426

2527
const originalCreatePolicy = trustedTypes.createPolicy.bind(trustedTypes);
2628

@@ -32,7 +34,7 @@ if (trustedTypes && trustedTypes.createPolicy) {
3234

3335
trustedTypes.createPolicy = function (name: string, rules: any) {
3436
if (name === "vue" || name.startsWith("vue-")) {
35-
console.log(
37+
debug(
3638
`[Subturtle] Intercepted policy creation for "${name}", returning passthrough`
3739
);
3840
return createPassthroughPolicy();
@@ -46,7 +48,7 @@ if (trustedTypes && trustedTypes.createPolicy) {
4648
}
4749
};
4850

49-
console.log("[Subturtle] Trusted Types workaround installed");
51+
debug("[Subturtle] Trusted Types workaround installed");
5052
}
5153

52-
export {};
54+
export { };

static/manifest.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "Subturtle",
33
"description": "Turn video subtitles into English lessons. Learn new vocabulary in context as you watch on YouTube and Netflix.",
4-
"version": "1.11.1",
4+
"version": "1.11.1.1",
55
"manifest_version": 3,
66
"icons": {
77
"128": "/assets/logo-128.png",
@@ -79,5 +79,6 @@
7979
"<all_urls>"
8080
]
8181
}
82-
]
83-
}
82+
],
83+
"version_name": "1.11.1-dev.1"
84+
}

0 commit comments

Comments
 (0)