Skip to content

Commit dfa0470

Browse files
committed
Fixed permissions issue when recording
1 parent 9d1871d commit dfa0470

File tree

6 files changed

+146
-53
lines changed

6 files changed

+146
-53
lines changed

src/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@
101101
"managed_schema": "schema.json"
102102
},
103103
"externally_connectable": {
104-
"matches": ["https://app.screenity.io/*"]
104+
"matches": ["https://app.screenity.io/*", "http://localhost:3000/*"]
105105
},
106106
"optional_permissions": [
107107
"offscreen",

src/pages/Background/listeners/onTabActivatedListener.js

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ export const handleTabActivation = async (activeInfo) => {
1414
"restarting",
1515
"pendingRecording",
1616
"recorderSession",
17+
"paused",
18+
"pausedAt",
19+
"totalPausedMs",
1720
]);
1821

1922
// Get the activated tab
@@ -58,19 +61,22 @@ export const handleTabActivation = async (activeInfo) => {
5861

5962
// If there's a recording start time, update the UI with time
6063
if (recordingStartTime) {
64+
const now = Date.now();
65+
const basePaused = totalPausedMs || 0;
66+
const extraPaused = paused && pausedAt ? Math.max(0, now - pausedAt) : 0;
67+
68+
const elapsed = Math.max(
69+
0,
70+
Math.floor((now - recordingStartTime - basePaused - extraPaused) / 1000)
71+
);
72+
6173
const { alarm } = await chrome.storage.local.get(["alarm"]);
6274
if (alarm) {
6375
const { alarmTime } = await chrome.storage.local.get(["alarmTime"]);
64-
const seconds = parseFloat(alarmTime);
65-
const time = Math.floor((Date.now() - recordingStartTime) / 1000);
66-
const remaining = seconds - time;
67-
sendMessageTab(activeInfo.tabId, {
68-
type: "time",
69-
time: remaining,
70-
});
76+
const remaining = Math.max(0, Math.floor(alarmTime - elapsed));
77+
sendMessageTab(activeInfo.tabId, { type: "time", time: remaining });
7178
} else {
72-
const time = Math.floor((Date.now() - recordingStartTime) / 1000);
73-
sendMessageTab(activeInfo.tabId, { type: "time", time: time });
79+
sendMessageTab(activeInfo.tabId, { type: "time", time: elapsed });
7480
}
7581
}
7682
} catch (error) {

src/pages/Background/listeners/onTabUpdatedListener.js

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ export const handleTabUpdate = async (tabId, changeInfo, tab) => {
1717
"pendingRecording",
1818
"recordingStartTime",
1919
"recorderSession",
20+
"paused",
21+
"pausedAt",
22+
"totalPausedMs",
2023
]);
2124

2225
// Check both recording flag AND recorderSession to avoid race conditions
@@ -41,20 +44,25 @@ export const handleTabUpdate = async (tabId, changeInfo, tab) => {
4144
}
4245

4346
if (recordingStartTime) {
44-
// Check if alarm
47+
const now = Date.now();
48+
const basePaused = totalPausedMs || 0;
49+
const extraPaused =
50+
paused && pausedAt ? Math.max(0, now - pausedAt) : 0;
51+
52+
const elapsed = Math.max(
53+
0,
54+
Math.floor(
55+
(now - recordingStartTime - basePaused - extraPaused) / 1000
56+
)
57+
);
58+
4559
const { alarm } = await chrome.storage.local.get(["alarm"]);
4660
if (alarm) {
4761
const { alarmTime } = await chrome.storage.local.get(["alarmTime"]);
48-
const seconds = parseFloat(alarmTime);
49-
const time = Math.floor((Date.now() - recordingStartTime) / 1000);
50-
const remaining = seconds - time;
51-
sendMessageTab(tabId, {
52-
type: "time",
53-
time: remaining,
54-
});
62+
const remaining = Math.max(0, Math.floor(alarmTime - elapsed));
63+
sendMessageTab(activeInfo.tabId, { type: "time", time: remaining });
5564
} else {
56-
const time = Math.floor((Date.now() - recordingStartTime) / 1000);
57-
sendMessageTab(tabId, { type: "time", time: time });
65+
sendMessageTab(activeInfo.tabId, { type: "time", time: elapsed });
5866
}
5967
}
6068

src/pages/Background/messaging/handlers.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -286,14 +286,14 @@ export const setupHandlers = () => {
286286
registerMessage("is-pinned", async () => await isPinned());
287287

288288
// Prevent Chrome from discarding the CloudRecorder tab during recording
289-
registerMessage("set-tab-auto-discardable", async ({ payload }, sender) => {
289+
registerMessage("set-tab-auto-discardable", async (message, sender) => {
290290
try {
291291
const tabId = sender?.tab?.id;
292-
if (tabId) {
293-
await chrome.tabs.update(tabId, {
294-
autoDiscardable: payload.discardable,
295-
});
296-
}
292+
const discardable = message?.discardable;
293+
294+
if (!tabId || typeof discardable !== "boolean") return;
295+
296+
await chrome.tabs.update(tabId, { autoDiscardable: discardable });
297297
} catch (err) {
298298
console.warn("Failed to set tab autoDiscardable:", err);
299299
}

src/pages/CloudRecorder/CloudRecorder.jsx

Lines changed: 58 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,7 @@ const CloudRecorder = () => {
699699
uploadMetaRef.current = null;
700700

701701
// FLAG: decide whether to close or not
702-
//window.close();
702+
// window.close();
703703
return;
704704
}
705705

@@ -727,7 +727,18 @@ const CloudRecorder = () => {
727727
isInit.current = false;
728728

729729
// FLAG: decide whether to close or not
730-
//window.close();
730+
if (!IS_IFRAME_CONTEXT) {
731+
try {
732+
window.close();
733+
} catch {}
734+
return;
735+
}
736+
// iframe context
737+
try {
738+
window.parent.postMessage({ type: "screenity-exit", mode }, "*");
739+
} catch {}
740+
// fallback
741+
window.location.reload();
731742
};
732743

733744
const restartRecording = async () => {
@@ -1805,31 +1816,31 @@ const CloudRecorder = () => {
18051816

18061817
const startAudioStream = async (id) => {
18071818
const audioStreamOptions = {
1808-
audio: {
1809-
deviceId: id ? { exact: id } : undefined,
1810-
},
1819+
audio: { deviceId: id ? { exact: id } : undefined },
18111820
};
18121821

18131822
try {
1814-
const stream = await navigator.mediaDevices.getUserMedia(
1815-
audioStreamOptions
1816-
);
1817-
return stream;
1823+
return await navigator.mediaDevices.getUserMedia(audioStreamOptions);
18181824
} catch (err) {
18191825
console.warn(
18201826
"⚠️ Failed to access audio with deviceId, trying fallback:",
18211827
err
18221828
);
1823-
1824-
// Fallback without deviceId
18251829
try {
1826-
const fallbackStream = await navigator.mediaDevices.getUserMedia({
1827-
audio: true,
1828-
});
1829-
return fallbackStream;
1830+
return await navigator.mediaDevices.getUserMedia({ audio: true });
18301831
} catch (err2) {
1831-
console.error("❌ Failed to access audio stream:", err2);
1832-
sendRecordingError("Failed to access audio stream: " + err2.message);
1832+
console.warn(
1833+
"⚠️ Microphone blocked/unavailable; continuing without mic:",
1834+
err2
1835+
);
1836+
1837+
// Optional: small non-fatal UI signal
1838+
chrome.runtime.sendMessage({
1839+
type: "show-toast",
1840+
message:
1841+
"Microphone permission is blocked. Recording will be silent.",
1842+
});
1843+
18331844
return null;
18341845
}
18351846
}
@@ -1924,10 +1935,22 @@ const CloudRecorder = () => {
19241935
cameraConstraints
19251936
);
19261937
} catch (err) {
1927-
sendRecordingError(
1928-
"Failed to access camera stream: " + err.message
1938+
console.warn(
1939+
"⚠️ Camera permission denied — continuing without camera:",
1940+
err
19291941
);
1930-
return;
1942+
cameraStream.current = null;
1943+
1944+
// keep UI consistent (optional)
1945+
await chrome.storage.local.set({ cameraActive: false });
1946+
1947+
// only fatal if the user is doing camera-only recording
1948+
if (data.recordingType === "camera") {
1949+
sendRecordingError(
1950+
"Camera permission is blocked. Please allow camera access to record."
1951+
);
1952+
return;
1953+
}
19311954
}
19321955
}
19331956

@@ -2063,10 +2086,22 @@ const CloudRecorder = () => {
20632086
cameraConstraints
20642087
);
20652088
} catch (err) {
2066-
sendRecordingError(
2067-
"Failed to access camera stream: " + err.message
2089+
console.warn(
2090+
"⚠️ Camera permission denied — continuing without camera:",
2091+
err
20682092
);
2069-
return;
2093+
cameraStream.current = null;
2094+
2095+
// keep UI consistent (optional)
2096+
await chrome.storage.local.set({ cameraActive: false });
2097+
2098+
// only fatal if the user is doing camera-only recording
2099+
if (data.recordingType === "camera") {
2100+
sendRecordingError(
2101+
"Camera permission is blocked. Please allow camera access to record."
2102+
);
2103+
return;
2104+
}
20702105
}
20712106
}
20722107
}

src/pages/Content/context/ContentState.jsx

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,9 @@ const ContentState = (props) => {
164164
recording: false,
165165
restarting: false,
166166
tabRecordedID: null,
167+
pausedAt: null,
168+
paused: false,
169+
totalPausedMs: 0,
167170
});
168171
setContentState((prevContentState) => ({
169172
...prevContentState,
@@ -202,9 +205,15 @@ const ContentState = (props) => {
202205
const pauseRecording = useCallback((dismiss) => {
203206
chrome.runtime.sendMessage({ type: "pause-recording-tab" });
204207

208+
const now = Date.now();
209+
chrome.storage.local.set({
210+
paused: true,
211+
pausedAt: now,
212+
});
213+
205214
setTimeout(() => {
206-
setContentState((prevContentState) => ({
207-
...prevContentState,
215+
setContentState((prev) => ({
216+
...prev,
208217
paused: true,
209218
}));
210219
if (!dismiss) {
@@ -218,8 +227,22 @@ const ContentState = (props) => {
218227

219228
const resumeRecording = useCallback(() => {
220229
chrome.runtime.sendMessage({ type: "resume-recording-tab" });
221-
setContentState((prevContentState) => ({
222-
...prevContentState,
230+
231+
const now = Date.now();
232+
chrome.storage.local.get(["pausedAt", "totalPausedMs"], (s) => {
233+
const pausedAt = s.pausedAt || now;
234+
const totalPausedMs = s.totalPausedMs || 0;
235+
const additional = Math.max(0, now - pausedAt);
236+
237+
chrome.storage.local.set({
238+
paused: false,
239+
pausedAt: null,
240+
totalPausedMs: totalPausedMs + additional,
241+
});
242+
});
243+
244+
setContentState((prev) => ({
245+
...prev,
223246
paused: false,
224247
}));
225248
});
@@ -242,6 +265,11 @@ const ContentState = (props) => {
242265
blurMode: false,
243266
drawingMode: false,
244267
}));
268+
chrome.storage.local.set({
269+
paused: false,
270+
pausedAt: null,
271+
totalPausedMs: 0,
272+
});
245273
// Remove blur from all elements
246274
const elements = document.querySelectorAll(".screenity-blur");
247275
elements.forEach((element) => {
@@ -674,6 +702,22 @@ const ContentState = (props) => {
674702
chrome.storage.local.set({ askForPermissions: false });
675703
});
676704

705+
useEffect(() => {
706+
const onChanged = (changes, area) => {
707+
if (area !== "local") return;
708+
709+
if (changes.paused) {
710+
setContentState((prev) => ({
711+
...prev,
712+
paused: Boolean(changes.paused.newValue),
713+
}));
714+
}
715+
};
716+
717+
chrome.storage.onChanged.addListener(onChanged);
718+
return () => chrome.storage.onChanged.removeListener(onChanged);
719+
}, []);
720+
677721
useEffect(() => {
678722
const handleMessage = (event) => {
679723
if (event.data.type === "screenity-permissions") {

0 commit comments

Comments
 (0)