Fix offline mode

This commit is contained in:
yflory 2025-06-17 14:45:25 +02:00
parent d915052829
commit 728a6db917
6 changed files with 48 additions and 23 deletions

View File

@ -2501,7 +2501,7 @@ const factory = (Sortify, UserObject, ProxyManager,
// don't always call onCacheReady and onReady?
// it depends on what was required by the first tab
onAccountCacheReady(returned => {
store.returned ||= returned;
store.cacheReturned ||= returned;
cacheCb(returned);
});
onAccountReady(returned => {
@ -2566,7 +2566,7 @@ const factory = (Sortify, UserObject, ProxyManager,
} = drive;
onDriveCacheReady(() => {
cacheCb(store.returned);
cacheCb(store.cacheReturned || store.returned);
});
onDriveReady(() => {
cb(store.returned);
@ -2637,7 +2637,8 @@ const factory = (Sortify, UserObject, ProxyManager,
};
// If we load CryptPad for the first time from an existing pad, don't create a
// drive automatically.
var onNoDrive = function (clientId, cb, initRpc) {
var onNoDrive = function (clientId, _cb, initRpc) {
const cb = Util.once(_cb);
var andThen = function () {
// Initialize modules that can be used by pads
// and don't require account data
@ -2649,30 +2650,37 @@ const factory = (Sortify, UserObject, ProxyManager,
cb({});
});
};
if (initRpc) {
// In integration mode, we may need an RPC
return initTempRpc(clientId, getAnon);
}
getAnon();
// We need to know the HistoryKeeper ID
// to initialize the anon RPC
loadHK(err => {
if (err) { return; }
if (initRpc) {
// In integration mode, we may need
// an authenticated RPC
return initTempRpc(clientId, getAnon);
}
getAnon();
});
// If initRpc is true, we need to wait for a network
// before calling back
if (!store.network && !initRpc) { cb({}); }
};
// We need an anonymous RPC to be able to check if the pad exists and to get
// its metadata, so we have to create a network first.
if (!store.network) {
var wsUrl = NetConfig.getWebsocketURL();
return void Netflux.connect(wsUrl).then(function (network) {
// If we already haave a network (race condition), use the
// existing one and forget this one
store.networkPromise = Netflux.connect(wsUrl);
andThen();
return store.networkPromise.then((network) => {
if (store.network === network) { return; }
// If we already haave a network (race condition)
// use the existing one and forget this one
if (!store.network) { store.network = network; }
else {
network.disconnect();
network = store.network;
}
// We need to know the HistoryKeeper ID to initialize the anon RPC
loadHK(err => {
if (err) { return void cb(err); }
andThen();
});
}, function (err) {
console.error(err);
cb({error: 'OFFLINE'});
@ -2752,6 +2760,12 @@ const factory = (Sortify, UserObject, ProxyManager,
startModules(clientId, ret, onInit);
});
});
Store.pad.onCacheReady(() => {
// If we're online, wait for onJoined
if (store.network) { return; }
// Otherwise, continue with cached drive
next();
});
Store.pad.onJoined(next);
onPadRejectedEvt.reg(next);
});
@ -2869,8 +2883,9 @@ const factory = (Sortify, UserObject, ProxyManager,
});
}
// If this is not the first tab (initialized is true), it means either we don't
// support offline or we're already online
// If this is not the first tab (initialized is true),
// it means either we don't support offline or we're
// already online
if (initialized) {
if (store.networkTimeout) {
postMessage(clientId, "LOADING_DRIVE", {

View File

@ -36,10 +36,12 @@ const init = (config) => {
// Create account secret from hash
const secret = Hash.getSecrets('drive', hash);
const network = config.store?.network ||
config.store?.networkPromise;
const listmapConfig = {
data: {},
websocketURL: NetConfig.getWebsocketURL(),
network: config.store?.network,
network: network,
channel: secret.channel,
readOnly: false,
validateKey: secret.keys?.validateKey || undefined,
@ -71,10 +73,14 @@ const init = (config) => {
}).on('cacheready', function (info) {
store.realtime = info.realtime;
store.offline = true;
store.networkPromise = info.networkPromise;
const hadPromise = !!store.networkPromise;
store.networkPromise ||= info.networkPromise;
store.cacheReturned = returned;
if (store.networkPromise && store.networkPromise.then) {
// Show error if we can't connect, but only if the accounts
// was required first
if (store.networkPromise && store.networkPromise.then
&& !hadPromise) {
// Check if we can connect
const to = setTimeout(function () {
store.networkTimeout = true;

View File

@ -21,6 +21,7 @@ import * as UserObject from '../../common/user-object.js';
import * as SF from './sharedfolder.js';
const onJoinedEvt: any = Util.mkEvent(true);
const onCacheReadyEvt: any = Util.mkEvent(true);
const _getMetadata: Callback = (ctx, clientId, data, _cb) => {
const cb = Util.once(Util.mkAsync(_cb));
@ -248,6 +249,7 @@ const _join: Callback = (ctx, clientId, data) => {
},
onCacheReady: () => {
postMessage(clientId, "PAD_CACHE_READY");
onCacheReadyEvt.fire();
},
onReady: pad => {
const padData = pad.metadata || {};
@ -527,6 +529,7 @@ const init = (config) => {
leave,
removeClient,
onJoined: onJoinedEvt.reg,
onCacheReady: onCacheReadyEvt.reg,
getChannels
};
};

View File

@ -89,6 +89,7 @@ export interface PadObject {
onCorruptedCache: RpcCall,
getChannels: () => string[],
onJoined: any,
onCacheReady: any,
}
export interface Pad {
init: (config: PadConfig) => PadObject

View File

@ -6,7 +6,7 @@
const factory = function (Channel, NodeWS) {
let USE_MIN = true;
if (typeof(localStorage) !== "undefined" &&
localStorage.CryptPad_dev === "1") { USE_MIN = false; }
localStorage.CryptPad_noMin === "1") { USE_MIN = false; }
let path = '/common/worker.bundle.js?';
if (USE_MIN) { path = '/common/worker.bundle.min.js?'; }

File diff suppressed because one or more lines are too long