@streamplace/components 0.8.11 → 0.8.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/chat/chat-message.d.ts.map +1 -1
- package/dist/components/chat/chat-message.js +5 -4
- package/dist/components/chat/chat-message.js.map +1 -1
- package/dist/components/chat/mod-view.d.ts.map +1 -1
- package/dist/components/chat/mod-view.js +4 -3
- package/dist/components/chat/mod-view.js.map +1 -1
- package/dist/components/mobile-player/ui/viewer-context-menu.d.ts.map +1 -1
- package/dist/components/mobile-player/ui/viewer-context-menu.js +3 -3
- package/dist/components/mobile-player/ui/viewer-context-menu.js.map +1 -1
- package/dist/components/share/sharesheet.d.ts.map +1 -1
- package/dist/components/share/sharesheet.js +5 -14
- package/dist/components/share/sharesheet.js.map +1 -1
- package/dist/components/ui/text.d.ts +2 -2
- package/dist/components/ui/view.d.ts +1 -1
- package/dist/i18n/i18n-loader.d.ts +2 -0
- package/dist/i18n/i18n-loader.d.ts.map +1 -0
- package/dist/i18n/i18n-loader.js +17 -0
- package/dist/i18n/i18n-loader.js.map +1 -0
- package/dist/i18n/i18n-loader.native.d.ts +2 -0
- package/dist/i18n/i18n-loader.native.d.ts.map +1 -0
- package/dist/i18n/i18n-loader.native.js +51 -0
- package/dist/i18n/i18n-loader.native.js.map +1 -0
- package/dist/i18n/i18next-config.d.ts.map +1 -1
- package/dist/i18n/i18next-config.js +5 -49
- package/dist/i18n/i18next-config.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/streamplace-provider/poller.d.ts.map +1 -1
- package/dist/streamplace-provider/poller.js +2 -0
- package/dist/streamplace-provider/poller.js.map +1 -1
- package/dist/time-sync/index.d.ts +3 -0
- package/dist/time-sync/index.d.ts.map +1 -0
- package/dist/time-sync/index.js +15 -0
- package/dist/time-sync/index.js.map +1 -0
- package/dist/time-sync/time-sync.d.ts +13 -0
- package/dist/time-sync/time-sync.d.ts.map +1 -0
- package/dist/time-sync/time-sync.js +95 -0
- package/dist/time-sync/time-sync.js.map +1 -0
- package/dist/time-sync/useTimeSync.d.ts +2 -0
- package/dist/time-sync/useTimeSync.d.ts.map +1 -0
- package/dist/time-sync/useTimeSync.js +49 -0
- package/dist/time-sync/useTimeSync.js.map +1 -0
- package/dist/utils/format-handle.d.ts +11 -0
- package/dist/utils/format-handle.d.ts.map +1 -0
- package/dist/utils/format-handle.js +21 -0
- package/dist/utils/format-handle.js.map +1 -0
- package/locales/en-US/common.ftl +5 -0
- package/locales/en-US/settings.ftl +7 -0
- package/locales/es-ES/common.ftl +5 -0
- package/locales/es-ES/settings.ftl +7 -0
- package/locales/fr-FR/common.ftl +5 -0
- package/locales/fr-FR/settings.ftl +7 -0
- package/locales/pt-BR/common.ftl +5 -0
- package/locales/pt-BR/settings.ftl +7 -0
- package/locales/zh-Hant/common.ftl +5 -0
- package/locales/zh-Hant/settings.ftl +7 -0
- package/node-compile-cache/v22.15.0-x64-efe9a9df-0/37be0eec +0 -0
- package/package.json +3 -3
- package/src/components/chat/chat-message.tsx +3 -2
- package/src/components/chat/mod-view.tsx +4 -3
- package/src/components/mobile-player/ui/viewer-context-menu.tsx +5 -3
- package/src/components/share/sharesheet.tsx +11 -27
- package/src/i18n/i18n-loader.native.ts +56 -0
- package/src/i18n/i18n-loader.ts +19 -0
- package/src/i18n/i18next-config.ts +6 -57
- package/src/index.tsx +2 -0
- package/src/streamplace-provider/poller.tsx +3 -0
- package/src/time-sync/index.ts +12 -0
- package/src/time-sync/time-sync.ts +112 -0
- package/src/time-sync/useTimeSync.tsx +58 -0
- package/src/utils/format-handle.ts +24 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/time-sync/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,aAAa,EACb,aAAa,EACb,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,aAAa,EACb,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useTimeSync = exports.syncTimeWithServer = exports.setTimeOffset = exports.initializeTimeSync = exports.getTimeOffset = exports.getSystemTime = exports.getSystemDate = exports.getSyncedDate = exports.checkClockDrift = void 0;
|
|
4
|
+
var time_sync_1 = require("./time-sync");
|
|
5
|
+
Object.defineProperty(exports, "checkClockDrift", { enumerable: true, get: function () { return time_sync_1.checkClockDrift; } });
|
|
6
|
+
Object.defineProperty(exports, "getSyncedDate", { enumerable: true, get: function () { return time_sync_1.getSyncedDate; } });
|
|
7
|
+
Object.defineProperty(exports, "getSystemDate", { enumerable: true, get: function () { return time_sync_1.getSystemDate; } });
|
|
8
|
+
Object.defineProperty(exports, "getSystemTime", { enumerable: true, get: function () { return time_sync_1.getSystemTime; } });
|
|
9
|
+
Object.defineProperty(exports, "getTimeOffset", { enumerable: true, get: function () { return time_sync_1.getTimeOffset; } });
|
|
10
|
+
Object.defineProperty(exports, "initializeTimeSync", { enumerable: true, get: function () { return time_sync_1.initializeTimeSync; } });
|
|
11
|
+
Object.defineProperty(exports, "setTimeOffset", { enumerable: true, get: function () { return time_sync_1.setTimeOffset; } });
|
|
12
|
+
Object.defineProperty(exports, "syncTimeWithServer", { enumerable: true, get: function () { return time_sync_1.syncTimeWithServer; } });
|
|
13
|
+
var useTimeSync_1 = require("./useTimeSync");
|
|
14
|
+
Object.defineProperty(exports, "useTimeSync", { enumerable: true, get: function () { return useTimeSync_1.useTimeSync; } });
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/time-sync/index.ts"],"names":[],"mappings":";;;AAAA,yCASqB;AARnB,4GAAA,eAAe,OAAA;AACf,0GAAA,aAAa,OAAA;AACb,0GAAA,aAAa,OAAA;AACb,0GAAA,aAAa,OAAA;AACb,0GAAA,aAAa,OAAA;AACb,+GAAA,kBAAkB,OAAA;AAClB,0GAAA,aAAa,OAAA;AACb,+GAAA,kBAAkB,OAAA;AAGpB,6CAA4C;AAAnC,0GAAA,WAAW,OAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare function getTimeOffset(): number;
|
|
2
|
+
export declare function setTimeOffset(offset: number): void;
|
|
3
|
+
export declare function checkClockDrift(serverTime: string): {
|
|
4
|
+
hasDrift: boolean;
|
|
5
|
+
driftMs: number;
|
|
6
|
+
driftSeconds: number;
|
|
7
|
+
};
|
|
8
|
+
export declare function syncTimeWithServer(serverTime: string, networkLatencyMs: number): void;
|
|
9
|
+
export declare function getSyncedDate(): Date;
|
|
10
|
+
export declare function getSystemDate(): Date;
|
|
11
|
+
export declare function getSystemTime(): number;
|
|
12
|
+
export declare function initializeTimeSync(): void;
|
|
13
|
+
//# sourceMappingURL=time-sync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time-sync.d.ts","sourceRoot":"","sources":["../../src/time-sync/time-sync.ts"],"names":[],"mappings":"AAQA,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAElD;AAED,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG;IACnD,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;CACtB,CAuBA;AAED,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,EAClB,gBAAgB,EAAE,MAAM,GACvB,IAAI,CAMN;AAED,wBAAgB,aAAa,IAAI,IAAI,CAMpC;AAED,wBAAgB,aAAa,IAAI,IAAI,CAEpC;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,wBAAgB,kBAAkB,IAAI,IAAI,CAuCzC"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getTimeOffset = getTimeOffset;
|
|
4
|
+
exports.setTimeOffset = setTimeOffset;
|
|
5
|
+
exports.checkClockDrift = checkClockDrift;
|
|
6
|
+
exports.syncTimeWithServer = syncTimeWithServer;
|
|
7
|
+
exports.getSyncedDate = getSyncedDate;
|
|
8
|
+
exports.getSystemDate = getSystemDate;
|
|
9
|
+
exports.getSystemTime = getSystemTime;
|
|
10
|
+
exports.initializeTimeSync = initializeTimeSync;
|
|
11
|
+
const react_native_1 = require("react-native");
|
|
12
|
+
let timeOffset = 0;
|
|
13
|
+
let hasWarned = false;
|
|
14
|
+
let OriginalDate = Date;
|
|
15
|
+
const CLOCK_DRIFT_THRESHOLD_MS = 5000; // 5 seconds
|
|
16
|
+
function getTimeOffset() {
|
|
17
|
+
return timeOffset;
|
|
18
|
+
}
|
|
19
|
+
function setTimeOffset(offset) {
|
|
20
|
+
timeOffset = offset;
|
|
21
|
+
}
|
|
22
|
+
function checkClockDrift(serverTime) {
|
|
23
|
+
const serverDate = new Date(serverTime);
|
|
24
|
+
const clientDate = new Date();
|
|
25
|
+
const drift = Math.abs(serverDate.getTime() - clientDate.getTime());
|
|
26
|
+
if (drift > CLOCK_DRIFT_THRESHOLD_MS) {
|
|
27
|
+
const driftSeconds = Math.round(drift / 1000);
|
|
28
|
+
if (!hasWarned) {
|
|
29
|
+
hasWarned = true;
|
|
30
|
+
console.warn(`clock drift detected: ${driftSeconds}s difference from server time. ` +
|
|
31
|
+
`this may cause issues with time-sensitive operations. ` +
|
|
32
|
+
`please sync your system clock.`);
|
|
33
|
+
}
|
|
34
|
+
return { hasDrift: true, driftMs: drift, driftSeconds };
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
return {
|
|
38
|
+
hasDrift: false,
|
|
39
|
+
driftMs: drift,
|
|
40
|
+
driftSeconds: Math.round(drift / 1000),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function syncTimeWithServer(serverTime, networkLatencyMs) {
|
|
45
|
+
const serverDate = new OriginalDate(serverTime);
|
|
46
|
+
const clientDate = new OriginalDate();
|
|
47
|
+
const offset = serverDate.getTime() - clientDate.getTime() - networkLatencyMs;
|
|
48
|
+
setTimeOffset(offset);
|
|
49
|
+
}
|
|
50
|
+
function getSyncedDate() {
|
|
51
|
+
const now = new Date();
|
|
52
|
+
if (timeOffset !== 0) {
|
|
53
|
+
return new Date(now.getTime() + timeOffset);
|
|
54
|
+
}
|
|
55
|
+
return now;
|
|
56
|
+
}
|
|
57
|
+
function getSystemDate() {
|
|
58
|
+
return new OriginalDate();
|
|
59
|
+
}
|
|
60
|
+
function getSystemTime() {
|
|
61
|
+
return OriginalDate.now();
|
|
62
|
+
}
|
|
63
|
+
function initializeTimeSync() {
|
|
64
|
+
if (react_native_1.Platform.OS !== "web") {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
// store original Date
|
|
68
|
+
OriginalDate = Date;
|
|
69
|
+
const OriginalDatePrototype = OriginalDate.prototype;
|
|
70
|
+
// create patched Date constructor
|
|
71
|
+
function PatchedDate(...args) {
|
|
72
|
+
// If called as a function (no `new`), forward to original Date to get the string form
|
|
73
|
+
if (!(this instanceof PatchedDate)) {
|
|
74
|
+
return OriginalDate.apply(undefined, args);
|
|
75
|
+
}
|
|
76
|
+
// If called as a constructor, construct a Date with synced time when no args provided
|
|
77
|
+
if (args.length === 0) {
|
|
78
|
+
const syncedTime = OriginalDate.now() + timeOffset;
|
|
79
|
+
return Reflect.construct(OriginalDate, [syncedTime], PatchedDate);
|
|
80
|
+
}
|
|
81
|
+
// Otherwise construct with the provided arguments
|
|
82
|
+
return Reflect.construct(OriginalDate, args, PatchedDate);
|
|
83
|
+
}
|
|
84
|
+
// copy static methods
|
|
85
|
+
PatchedDate.now = function () {
|
|
86
|
+
return OriginalDate.now() + timeOffset;
|
|
87
|
+
};
|
|
88
|
+
PatchedDate.parse = OriginalDate.parse;
|
|
89
|
+
PatchedDate.UTC = OriginalDate.UTC;
|
|
90
|
+
// copy prototype
|
|
91
|
+
PatchedDate.prototype = OriginalDatePrototype;
|
|
92
|
+
// replace global Date
|
|
93
|
+
globalThis.Date = PatchedDate;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=time-sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time-sync.js","sourceRoot":"","sources":["../../src/time-sync/time-sync.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTimeSync.d.ts","sourceRoot":"","sources":["../../src/time-sync/useTimeSync.tsx"],"names":[],"mappings":"AAQA,wBAAgB,WAAW,SAiD1B"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useTimeSync = useTimeSync;
|
|
4
|
+
const lucide_react_native_1 = require("lucide-react-native");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const react_native_1 = require("react-native");
|
|
7
|
+
const streamplace_1 = require("streamplace");
|
|
8
|
+
const toast_1 = require("../components/ui/toast");
|
|
9
|
+
const streamplace_store_1 = require("../streamplace-store/streamplace-store");
|
|
10
|
+
const time_sync_1 = require("./time-sync");
|
|
11
|
+
function useTimeSync() {
|
|
12
|
+
const url = (0, streamplace_store_1.useUrl)();
|
|
13
|
+
const t = (0, toast_1.useToast)();
|
|
14
|
+
const hasShownWarning = (0, react_1.useRef)(false);
|
|
15
|
+
(0, react_1.useEffect)(() => {
|
|
16
|
+
const checkTime = async () => {
|
|
17
|
+
if (react_native_1.Platform.OS !== "web") {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
const agent = new streamplace_1.StreamplaceAgent(url);
|
|
22
|
+
const start = new Date().getTime();
|
|
23
|
+
const response = await agent.place.stream.server.getServerTime();
|
|
24
|
+
const roundTripLatency = new Date().getTime() - start;
|
|
25
|
+
const serverTime = response.data.serverTime;
|
|
26
|
+
// always sync with server time
|
|
27
|
+
(0, time_sync_1.syncTimeWithServer)(serverTime, roundTripLatency / 2);
|
|
28
|
+
const driftInfo = (0, time_sync_1.checkClockDrift)(serverTime);
|
|
29
|
+
// only show warning if drift is significant
|
|
30
|
+
if (driftInfo.hasDrift && !hasShownWarning.current) {
|
|
31
|
+
hasShownWarning.current = true;
|
|
32
|
+
t.show("Clock drift detected!", `Your device clock is ${driftInfo.driftSeconds}s off from server time. Please sync your system clock to avoid issues.`, {
|
|
33
|
+
variant: "info",
|
|
34
|
+
iconLeft: lucide_react_native_1.TriangleAlert,
|
|
35
|
+
duration: 25,
|
|
36
|
+
});
|
|
37
|
+
console.log(`time sync applied: offset ${driftInfo.driftMs}ms. Date() calls will now use server time.`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
console.error("failed to sync time with server:", error);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
checkTime();
|
|
45
|
+
const interval = setInterval(checkTime, 1800000); // every 30m
|
|
46
|
+
return () => clearInterval(interval);
|
|
47
|
+
}, [url, t]);
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=useTimeSync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTimeSync.js","sourceRoot":"","sources":["../../src/time-sync/useTimeSync.tsx"],"names":[],"mappings":";;AAQA,kCAiDC;AAzDD,6DAAoD;AACpD,iCAA0C;AAC1C,+CAAwC;AACxC,6CAA+C;AAC/C,kDAAkD;AAClD,8EAAgE;AAChE,2CAAkE;AAElE,SAAgB,WAAW;IACzB,MAAM,GAAG,GAAG,IAAA,0BAAM,GAAE,CAAC;IACrB,MAAM,CAAC,GAAG,IAAA,gBAAQ,GAAE,CAAC;IACrB,MAAM,eAAe,GAAG,IAAA,cAAM,EAAC,KAAK,CAAC,CAAC;IAEtC,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,MAAM,SAAS,GAAG,KAAK,IAAI,EAAE;YAC3B,IAAI,uBAAQ,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;gBAC1B,OAAO;YACT,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,IAAI,8BAAgB,CAAC,GAAG,CAAC,CAAC;gBACxC,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC;gBACnC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;gBACjE,MAAM,gBAAgB,GAAG,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC;gBACtD,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC;gBAE5C,+BAA+B;gBAC/B,IAAA,8BAAkB,EAAC,UAAU,EAAE,gBAAgB,GAAG,CAAC,CAAC,CAAC;gBAErD,MAAM,SAAS,GAAG,IAAA,2BAAe,EAAC,UAAU,CAAC,CAAC;gBAE9C,4CAA4C;gBAC5C,IAAI,SAAS,CAAC,QAAQ,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,CAAC;oBACnD,eAAe,CAAC,OAAO,GAAG,IAAI,CAAC;oBAC/B,CAAC,CAAC,IAAI,CACJ,uBAAuB,EACvB,wBAAwB,SAAS,CAAC,YAAY,wEAAwE,EACtH;wBACE,OAAO,EAAE,MAAM;wBACf,QAAQ,EAAE,mCAAa;wBACvB,QAAQ,EAAE,EAAE;qBACb,CACF,CAAC;oBACF,OAAO,CAAC,GAAG,CACT,6BAA6B,SAAS,CAAC,OAAO,4CAA4C,CAC3F,CAAC;gBACJ,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,KAAK,CAAC,CAAC;YAC3D,CAAC;QACH,CAAC,CAAC;QAEF,SAAS,EAAE,CAAC;QAEZ,MAAM,QAAQ,GAAG,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,YAAY;QAE9D,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { AppBskyActorDefs } from "@atproto/api";
|
|
2
|
+
/**
|
|
3
|
+
* formats a user's handle for display, falling back to DID if handle is invalid
|
|
4
|
+
*/
|
|
5
|
+
export declare function formatHandle(profile: Pick<AppBskyActorDefs.ProfileViewBasic, "handle" | "did">, prefix?: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* convenience function for formatting a user's handle with @ prefix for display,
|
|
8
|
+
* falling back to DID if handle is invalid
|
|
9
|
+
*/
|
|
10
|
+
export declare function formatHandleWithAt(profile: Pick<AppBskyActorDefs.ProfileViewBasic, "handle" | "did">): string;
|
|
11
|
+
//# sourceMappingURL=format-handle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format-handle.d.ts","sourceRoot":"","sources":["../../src/utils/format-handle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD;;GAEG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,IAAI,CAAC,gBAAgB,CAAC,gBAAgB,EAAE,QAAQ,GAAG,KAAK,CAAC,EAClE,MAAM,GAAE,MAAW,GAClB,MAAM,CAKR;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,IAAI,CAAC,gBAAgB,CAAC,gBAAgB,EAAE,QAAQ,GAAG,KAAK,CAAC,GACjE,MAAM,CAER"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatHandle = formatHandle;
|
|
4
|
+
exports.formatHandleWithAt = formatHandleWithAt;
|
|
5
|
+
/**
|
|
6
|
+
* formats a user's handle for display, falling back to DID if handle is invalid
|
|
7
|
+
*/
|
|
8
|
+
function formatHandle(profile, prefix = "") {
|
|
9
|
+
if (profile.handle === "handle.invalid") {
|
|
10
|
+
return profile.did;
|
|
11
|
+
}
|
|
12
|
+
return prefix + profile.handle;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* convenience function for formatting a user's handle with @ prefix for display,
|
|
16
|
+
* falling back to DID if handle is invalid
|
|
17
|
+
*/
|
|
18
|
+
function formatHandleWithAt(profile) {
|
|
19
|
+
return formatHandle(profile, "@");
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=format-handle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format-handle.js","sourceRoot":"","sources":["../../src/utils/format-handle.ts"],"names":[],"mappings":";;AAKA,oCAQC;AAMD,gDAIC;AArBD;;GAEG;AACH,SAAgB,YAAY,CAC1B,OAAkE,EAClE,SAAiB,EAAE;IAEnB,IAAI,OAAO,CAAC,MAAM,KAAK,gBAAgB,EAAE,CAAC;QACxC,OAAO,OAAO,CAAC,GAAG,CAAC;IACrB,CAAC;IACD,OAAO,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;AACjC,CAAC;AAED;;;GAGG;AACH,SAAgB,kBAAkB,CAChC,OAAkE;IAElE,OAAO,YAAY,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;AACpC,CAAC"}
|
package/locales/en-US/common.ftl
CHANGED
|
@@ -32,6 +32,11 @@ info = Information
|
|
|
32
32
|
search-placeholder = Search...
|
|
33
33
|
message-input = Enter your message...
|
|
34
34
|
|
|
35
|
+
## Authentication & Access
|
|
36
|
+
please-log-in-to-access-this-page = Please log in to access this page
|
|
37
|
+
go-to-settings = Go to Settings
|
|
38
|
+
go-back = Go Back
|
|
39
|
+
|
|
35
40
|
## Demo and Testing
|
|
36
41
|
welcome-user = Welcome, { $username }!
|
|
37
42
|
notification-count = { $count ->
|
|
@@ -45,6 +45,7 @@ settings-title = Settings
|
|
|
45
45
|
|
|
46
46
|
## Navigation Categories
|
|
47
47
|
about = About
|
|
48
|
+
account = Account
|
|
48
49
|
advanced = Advanced
|
|
49
50
|
danmu = Danmu
|
|
50
51
|
developer = Developer
|
|
@@ -60,6 +61,12 @@ refresh = Refresh
|
|
|
60
61
|
save-button = Save
|
|
61
62
|
sign-in = Sign In
|
|
62
63
|
update = Update
|
|
64
|
+
log-out = Log out
|
|
65
|
+
|
|
66
|
+
## Account Settings
|
|
67
|
+
account-greeting = Hey, @{ $handle }.
|
|
68
|
+
edit-profile-bluesky = Edit profile (on Bluesky)
|
|
69
|
+
change-name-color = Change name color
|
|
63
70
|
|
|
64
71
|
## Key Management
|
|
65
72
|
key-management = Key Management
|
package/locales/es-ES/common.ftl
CHANGED
|
@@ -32,6 +32,11 @@ info = Información
|
|
|
32
32
|
search-placeholder = Buscar...
|
|
33
33
|
message-input = Escribe tu mensaje...
|
|
34
34
|
|
|
35
|
+
## Authentication & Access
|
|
36
|
+
please-log-in-to-access-this-page = Por favor, inicia sesión para acceder a esta página
|
|
37
|
+
go-to-settings = Ir a Configuración
|
|
38
|
+
go-back = Volver
|
|
39
|
+
|
|
35
40
|
## Demo and Testing
|
|
36
41
|
welcome-user = ¡Bienvenido, { $username }!
|
|
37
42
|
notification-count = { $count ->
|
|
@@ -84,6 +84,7 @@ finish = Finalizar
|
|
|
84
84
|
|
|
85
85
|
## Categorías de Navegación
|
|
86
86
|
about = Acerca de
|
|
87
|
+
account = Cuenta
|
|
87
88
|
advanced = Avanzado
|
|
88
89
|
danmu = Danmu
|
|
89
90
|
developer = Desarrollador
|
|
@@ -99,6 +100,12 @@ refresh = Actualizar
|
|
|
99
100
|
save-button = Guardar
|
|
100
101
|
sign-in = Iniciar Sesión
|
|
101
102
|
update = Actualizar
|
|
103
|
+
log-out = Cerrar sesión
|
|
104
|
+
|
|
105
|
+
## Configuración de Cuenta
|
|
106
|
+
account-greeting = Hola, @{ $handle }.
|
|
107
|
+
edit-profile-bluesky = Editar perfil (en Bluesky)
|
|
108
|
+
change-name-color = Cambiar color de nombre
|
|
102
109
|
|
|
103
110
|
## Gestión de Claves
|
|
104
111
|
key-management = Gestión de Claves
|
package/locales/fr-FR/common.ftl
CHANGED
|
@@ -32,6 +32,11 @@ info = Information
|
|
|
32
32
|
search-placeholder = Rechercher...
|
|
33
33
|
message-input = Entrez votre message...
|
|
34
34
|
|
|
35
|
+
## Authentication & Access
|
|
36
|
+
please-log-in-to-access-this-page = Veuillez vous connecter pour accéder à cette page
|
|
37
|
+
go-to-settings = Aller aux Paramètres
|
|
38
|
+
go-back = Retour
|
|
39
|
+
|
|
35
40
|
## Demo and Testing
|
|
36
41
|
welcome-user = Bienvenue, { $username } !
|
|
37
42
|
notification-count = { $count ->
|
|
@@ -82,6 +82,7 @@ finish = Terminer
|
|
|
82
82
|
|
|
83
83
|
## Catégories de Navigation
|
|
84
84
|
about = À propos
|
|
85
|
+
account = Compte
|
|
85
86
|
advanced = Avancé
|
|
86
87
|
danmu = Danmu
|
|
87
88
|
developer = Développeur
|
|
@@ -97,6 +98,12 @@ refresh = Actualiser
|
|
|
97
98
|
save-button = Enregistrer
|
|
98
99
|
sign-in = Se connecter
|
|
99
100
|
update = Mettre à jour
|
|
101
|
+
log-out = Se déconnecter
|
|
102
|
+
|
|
103
|
+
## Paramètres du Compte
|
|
104
|
+
account-greeting = Salut, @{ $handle }.
|
|
105
|
+
edit-profile-bluesky = Modifier le profil (sur Bluesky)
|
|
106
|
+
change-name-color = Changer la couleur du nom
|
|
100
107
|
|
|
101
108
|
## Gestion des Clés
|
|
102
109
|
key-management = Gestion des Clés
|
package/locales/pt-BR/common.ftl
CHANGED
|
@@ -32,6 +32,11 @@ info = Informação
|
|
|
32
32
|
search-placeholder = Pesquisar...
|
|
33
33
|
message-input = Digite sua mensagem...
|
|
34
34
|
|
|
35
|
+
## Authentication & Access
|
|
36
|
+
please-log-in-to-access-this-page = Por favor, faça login para acessar esta página
|
|
37
|
+
go-to-settings = Ir para Configurações
|
|
38
|
+
go-back = Voltar
|
|
39
|
+
|
|
35
40
|
## Demo and Testing
|
|
36
41
|
welcome-user = Bem-vindo, { $username }!
|
|
37
42
|
notification-count = { $count ->
|
|
@@ -82,6 +82,7 @@ finish = Finalizar
|
|
|
82
82
|
|
|
83
83
|
## Categorias de Navegação
|
|
84
84
|
about = Sobre
|
|
85
|
+
account = Conta
|
|
85
86
|
advanced = Avançado
|
|
86
87
|
danmu = Danmu
|
|
87
88
|
developer = Desenvolvedor
|
|
@@ -97,6 +98,12 @@ refresh = Atualizar
|
|
|
97
98
|
save-button = Salvar
|
|
98
99
|
sign-in = Entrar
|
|
99
100
|
update = Atualizar
|
|
101
|
+
log-out = Sair
|
|
102
|
+
|
|
103
|
+
## Configurações da Conta
|
|
104
|
+
account-greeting = Olá, @{ $handle }.
|
|
105
|
+
edit-profile-bluesky = Editar perfil (no Bluesky)
|
|
106
|
+
change-name-color = Mudar cor do nome
|
|
100
107
|
|
|
101
108
|
## Gerenciamento de Chaves
|
|
102
109
|
key-management = Gerenciamento de Chaves
|
|
@@ -32,6 +32,11 @@ info = 資訊
|
|
|
32
32
|
search-placeholder = 搜尋...
|
|
33
33
|
message-input = 輸入您的訊息...
|
|
34
34
|
|
|
35
|
+
## Authentication & Access
|
|
36
|
+
please-log-in-to-access-this-page = 請登入以存取此頁面
|
|
37
|
+
go-to-settings = 前往設定
|
|
38
|
+
go-back = 返回
|
|
39
|
+
|
|
35
40
|
## Demo and Testing
|
|
36
41
|
welcome-user = 歡迎,{ $username }!
|
|
37
42
|
notification-count = { $count ->
|
|
@@ -83,6 +83,7 @@ finish = 完成
|
|
|
83
83
|
|
|
84
84
|
## 導航類別
|
|
85
85
|
about = 關於
|
|
86
|
+
account = 帳戶
|
|
86
87
|
advanced = 進階
|
|
87
88
|
danmu = 彈幕
|
|
88
89
|
developer = 開發者
|
|
@@ -98,6 +99,12 @@ refresh = 重新整理
|
|
|
98
99
|
save-button = 儲存
|
|
99
100
|
sign-in = 登入
|
|
100
101
|
update = 更新
|
|
102
|
+
log-out = 登出
|
|
103
|
+
|
|
104
|
+
## 帳戶設定
|
|
105
|
+
account-greeting = 嗨,@{ $handle }。
|
|
106
|
+
edit-profile-bluesky = 編輯個人資料(在 Bluesky)
|
|
107
|
+
change-name-color = 變更名稱顏色
|
|
101
108
|
|
|
102
109
|
## 金鑰管理
|
|
103
110
|
key-management = 金鑰管理
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@streamplace/components",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.13",
|
|
4
4
|
"description": "Streamplace React (Native) Components",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "src/index.tsx",
|
|
@@ -72,10 +72,10 @@
|
|
|
72
72
|
"scripts": {
|
|
73
73
|
"build": "tsc",
|
|
74
74
|
"start": "tsc --watch --preserveWatchOutput",
|
|
75
|
-
"prepare": "
|
|
75
|
+
"prepare": "node scripts/compile-translations.js && tsc",
|
|
76
76
|
"i18n:compile": "node scripts/compile-translations.js",
|
|
77
77
|
"i18n:watch": "nodemon scripts/compile-translations.js --watch locales/**/*.ftl",
|
|
78
78
|
"i18n:extract": "node scripts/extract-i18n.js"
|
|
79
79
|
},
|
|
80
|
-
"gitHead": "
|
|
80
|
+
"gitHead": "abc60b0b81cfa69ae99e78781976199f0762f941"
|
|
81
81
|
}
|
|
@@ -8,6 +8,7 @@ import { Linking, View } from "react-native";
|
|
|
8
8
|
import { ChatMessageViewHydrated } from "streamplace";
|
|
9
9
|
import { RichtextSegment, segmentize } from "../../lib/facet";
|
|
10
10
|
import { borders, flex, gap, ml, mr, opacity, pl } from "../../lib/theme/atoms";
|
|
11
|
+
import { formatHandleWithAt } from "../../utils/format-handle";
|
|
11
12
|
import { atoms, colors, layout } from "../ui";
|
|
12
13
|
|
|
13
14
|
interface Facet {
|
|
@@ -138,7 +139,7 @@ export const RenderChatMessage = memo(
|
|
|
138
139
|
fontWeight: "thin",
|
|
139
140
|
}}
|
|
140
141
|
>
|
|
141
|
-
|
|
142
|
+
{formatHandleWithAt(replyTo.author)}
|
|
142
143
|
</Text>{" "}
|
|
143
144
|
<Text
|
|
144
145
|
style={{
|
|
@@ -181,7 +182,7 @@ export const RenderChatMessage = memo(
|
|
|
181
182
|
},
|
|
182
183
|
]}
|
|
183
184
|
>
|
|
184
|
-
|
|
185
|
+
{formatHandleWithAt(item.author)}
|
|
185
186
|
</Text>
|
|
186
187
|
:{" "}
|
|
187
188
|
<RichTextMessage
|
|
@@ -12,6 +12,7 @@ import { Linking } from "react-native";
|
|
|
12
12
|
import { ChatMessageViewHydrated } from "streamplace";
|
|
13
13
|
import { useDeleteChatMessage } from "../../livestream-store";
|
|
14
14
|
import { useStreamplaceStore } from "../../streamplace-store";
|
|
15
|
+
import { formatHandle, formatHandleWithAt } from "../../utils/format-handle";
|
|
15
16
|
import {
|
|
16
17
|
atoms,
|
|
17
18
|
DropdownMenu,
|
|
@@ -113,7 +114,7 @@ export const ModView = forwardRef<ModViewRef, ModViewProps>(() => {
|
|
|
113
114
|
minute: "2-digit",
|
|
114
115
|
hour12: false,
|
|
115
116
|
})}{" "}
|
|
116
|
-
|
|
117
|
+
{formatHandleWithAt(message.author)}: {message.record.text}
|
|
117
118
|
</Text>
|
|
118
119
|
</View>
|
|
119
120
|
</DropdownMenuItem>
|
|
@@ -159,7 +160,7 @@ export const ModView = forwardRef<ModViewRef, ModViewProps>(() => {
|
|
|
159
160
|
<Text color="destructive">
|
|
160
161
|
{isBlockLoading
|
|
161
162
|
? "Blocking..."
|
|
162
|
-
: `Block user
|
|
163
|
+
: `Block user ${formatHandleWithAt(message.author)} from this channel`}
|
|
163
164
|
</Text>
|
|
164
165
|
)}
|
|
165
166
|
</DropdownMenuItem>
|
|
@@ -170,7 +171,7 @@ export const ModView = forwardRef<ModViewRef, ModViewProps>(() => {
|
|
|
170
171
|
<DropdownMenuItem
|
|
171
172
|
onPress={() => {
|
|
172
173
|
Linking.openURL(
|
|
173
|
-
`https://${BSKY_FRONTEND_DOMAIN}/profile/${message.author
|
|
174
|
+
`https://${BSKY_FRONTEND_DOMAIN}/profile/${formatHandle(message.author)}`,
|
|
174
175
|
);
|
|
175
176
|
}}
|
|
176
177
|
>
|
|
@@ -4,6 +4,8 @@ import { Image, Linking, Platform, Pressable, View } from "react-native";
|
|
|
4
4
|
import {
|
|
5
5
|
ContentRights,
|
|
6
6
|
ContentWarnings,
|
|
7
|
+
formatHandle,
|
|
8
|
+
formatHandleWithAt,
|
|
7
9
|
useAvatars,
|
|
8
10
|
useLivestreamInfo,
|
|
9
11
|
zero,
|
|
@@ -113,12 +115,12 @@ export function ContextMenu({
|
|
|
113
115
|
<Pressable
|
|
114
116
|
onPress={() => {
|
|
115
117
|
if (profile?.handle) {
|
|
116
|
-
const url = `https://bsky.app/profile/${profile
|
|
118
|
+
const url = `https://bsky.app/profile/${formatHandle(profile)}`;
|
|
117
119
|
Linking.openURL(url);
|
|
118
120
|
}
|
|
119
121
|
}}
|
|
120
122
|
>
|
|
121
|
-
<Text
|
|
123
|
+
<Text>{profile && formatHandleWithAt(profile)}</Text>
|
|
122
124
|
</Pressable>
|
|
123
125
|
{/*{did && profile && (
|
|
124
126
|
<FollowButton streamerDID={profile?.did} currentUserDID={did} />
|
|
@@ -163,7 +165,7 @@ export function ContextMenu({
|
|
|
163
165
|
<DropdownMenuItem
|
|
164
166
|
onPress={() => {
|
|
165
167
|
if (profile?.handle) {
|
|
166
|
-
const url = `https://bsky.app/profile/${profile
|
|
168
|
+
const url = `https://bsky.app/profile/${formatHandle(profile)}`;
|
|
167
169
|
Linking.openURL(url);
|
|
168
170
|
}
|
|
169
171
|
}}
|
|
@@ -4,6 +4,7 @@ import { Clipboard, Linking, Platform, View } from "react-native";
|
|
|
4
4
|
import { colors } from "../../lib/theme";
|
|
5
5
|
import { useLivestreamStore } from "../../livestream-store";
|
|
6
6
|
import { useUrl } from "../../streamplace-store";
|
|
7
|
+
import { formatHandle } from "../../utils/format-handle";
|
|
7
8
|
import { BlueskyIcon } from "../icons/bluesky-icon";
|
|
8
9
|
import {
|
|
9
10
|
DropdownMenu,
|
|
@@ -26,12 +27,12 @@ export function ShareSheet({ onShare }: ShareSheetProps = {}) {
|
|
|
26
27
|
|
|
27
28
|
// Get the current stream URL
|
|
28
29
|
const getStreamUrl = useCallback(() => {
|
|
29
|
-
return url + (profile ?
|
|
30
|
+
return url + (profile ? `/${formatHandle(profile)}` : "");
|
|
30
31
|
}, [profile]);
|
|
31
32
|
|
|
32
33
|
// Get the embed URL
|
|
33
34
|
const getEmbedUrl = useCallback(() => {
|
|
34
|
-
return url + (profile ? `/embed/${profile
|
|
35
|
+
return url + (profile ? `/embed/${formatHandle(profile)}` : "");
|
|
35
36
|
}, [profile]);
|
|
36
37
|
|
|
37
38
|
// Get embed code
|
|
@@ -63,31 +64,22 @@ export function ShareSheet({ onShare }: ShareSheetProps = {}) {
|
|
|
63
64
|
// Share to Bluesky
|
|
64
65
|
const shareToBluesky = useCallback(() => {
|
|
65
66
|
const streamUrl = getStreamUrl();
|
|
66
|
-
const text =
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
const text =
|
|
68
|
+
profile && profile.handle
|
|
69
|
+
? `Check out @${profile.handle} live on Streamplace! ${streamUrl}`
|
|
70
|
+
: `Check out this stream on Streamplace! ${streamUrl}`;
|
|
69
71
|
const blueskyUrl = `https://bsky.app/intent/compose?text=${encodeURIComponent(text)}`;
|
|
70
72
|
Linking.openURL(blueskyUrl);
|
|
71
73
|
onShare?.("share_bluesky", true);
|
|
72
74
|
}, [profile, getStreamUrl, onShare]);
|
|
73
75
|
|
|
74
|
-
// Share to Twitter/X
|
|
75
|
-
const shareToTwitter = useCallback(() => {
|
|
76
|
-
const streamUrl = getStreamUrl();
|
|
77
|
-
const text = profile
|
|
78
|
-
? `Check out @${profile.handle} live on Streamplace!`
|
|
79
|
-
: `Check out this stream on Streamplace!`;
|
|
80
|
-
const twitterUrl = `https://twitter.com/intent/tweet?text=${encodeURIComponent(text)}&url=${encodeURIComponent(streamUrl)}`;
|
|
81
|
-
Linking.openURL(twitterUrl);
|
|
82
|
-
onShare?.("share_twitter", true);
|
|
83
|
-
}, [profile, getStreamUrl, onShare]);
|
|
84
|
-
|
|
85
76
|
// Native share (mobile)
|
|
86
77
|
const nativeShare = useCallback(async () => {
|
|
87
78
|
const streamUrl = getStreamUrl();
|
|
88
|
-
const text =
|
|
89
|
-
|
|
90
|
-
|
|
79
|
+
const text =
|
|
80
|
+
profile && profile.handle
|
|
81
|
+
? `Check out @${profile.handle} live on Streamplace!`
|
|
82
|
+
: `Check out this stream on Streamplace!`;
|
|
91
83
|
|
|
92
84
|
if (Platform.OS === "web" && navigator.share) {
|
|
93
85
|
try {
|
|
@@ -119,14 +111,6 @@ export function ShareSheet({ onShare }: ShareSheetProps = {}) {
|
|
|
119
111
|
<Text>Share to Bluesky</Text>
|
|
120
112
|
</View>
|
|
121
113
|
</DropdownMenuItem>
|
|
122
|
-
{/* <DropdownMenuItem onPress={shareToTwitter}>
|
|
123
|
-
<View
|
|
124
|
-
style={{ flexDirection: "row", alignItems: "center", gap: 12 }}
|
|
125
|
-
>
|
|
126
|
-
<MessageCircle size={20} color={colors.gray[400]} />
|
|
127
|
-
<Text>Share to X</Text>
|
|
128
|
-
</View>
|
|
129
|
-
</DropdownMenuItem> */}
|
|
130
114
|
{/* navigator isn't on non-web */}
|
|
131
115
|
{Platform.OS !== "web" || (navigator && (navigator as any).share) ? (
|
|
132
116
|
<DropdownMenuItem onPress={nativeShare}>
|