Merge branch 'staging' into update-icons

# Conflicts:
#	customize.dist/src/less2/include/toolbar.less
#	www/calendar/app-calendar.less
#	www/calendar/inner.js
This commit is contained in:
daria 2025-09-16 17:30:52 +03:00
commit 71e5b53950
No known key found for this signature in database
GPG Key ID: 3B75240E6B2F2701
31 changed files with 290 additions and 41 deletions

View File

@ -89,10 +89,9 @@ body:
label: Version
description: What version of CryptPad are you running?
options:
- 2025.6.0
- 2025.3.1
- 2025.3.0
- 2024.12.0
- 2024.9.1
- 2024.9.0
- Other
validations:
required: true

39
.github/workflows/test-trigger.yml vendored Normal file
View File

@ -0,0 +1,39 @@
# SPDX-FileCopyrightText: 2025 2023 XWiki CryptPad Team <contact@cryptpad.org> and contributors
#
# SPDX-License-Identifier: AGPL-3.0-or-later
name: Trigger E2E tests
on:
push:
branches: [ staging, 2025.9-rc, 2025.9-test ]
jobs:
trigger-tests:
if: github.ref_name == 'staging'
runs-on: ubuntu-latest
steps:
- name: Trigger E2E test run (local)
run: |
branch="${GITHUB_REF_NAME}"
if [ "$branch" = "staging" ]; then
event_type="trigger-e2e-tests-staging"
elif [ "$branch" = "2025.9-rc" ]; then
event_type="trigger-e2e-tests-rc"
elif [ "$branch" = "2025.9-test" ]; then
event_type="trigger-e2e-tests-test"
fi
repo_owner="cryptpad"
repo_name="e2e-test-suite"
curl -L \
-X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.TEST_PAT }}" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/cryptpad/e2e-test-suite/dispatches \
-d "{\"event_type\": \"$event_type\", \"client_payload\": {\"service\": \"$service\", \"version\": \"$version\", \"unit\": false, \"integration\": true}}"

View File

@ -61,7 +61,7 @@
.cp-markdown-toolbar {
min-height: @toolbar_line-height;
padding: 0.1rem 0;
padding: 0.15rem 0.20rem;
height: auto;
flex-wrap: wrap;
background-color: @cp_toolbar-bg;
@ -73,6 +73,7 @@
border-radius: @variables_radius;
color: @toolbar-color;
.toolbar_button;
padding: 3px 9px;
&:hover {
background-color: contrast(@cp_toolbar-bg, darken(@cp_toolbar-bg, 5%), lighten(@cp_toolbar-bg, 5%));
}

View File

@ -255,6 +255,30 @@ server {
add_header Cross-Origin-Embedder-Policy require-corp;
}
location ~ ^/upload-blob {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' "${allowed_origins}";
add_header 'Access-Control-Allow-Credentials' true;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range,Authorization';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'application/octet-stream; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
proxy_pass http://localhost:3000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# These settings prevent both NGINX and the API server
# from setting the same headers and creating duplicates
proxy_hide_header Cross-Origin-Resource-Policy;
add_header Cross-Origin-Resource-Policy cross-origin;
proxy_hide_header Cross-Origin-Embedder-Policy;
add_header Cross-Origin-Embedder-Policy require-corp;
}
# Requests for blobs and blocks are now proxied to the API server
# This simplifies NGINX path configuration in the event they are being hosted in a non-standard location
# or with odd unexpected permissions. Serving blobs in this manner also means that it will be possible to

View File

@ -1,4 +1,4 @@
!/bin/sh
#!/bin/sh
# $FreeBSD$
# PROVIDE: cryptpad
# REQUIRE: DAEMON nginx

View File

@ -98,7 +98,7 @@ module.exports.create = function (config) {
protocol: new URL(httpUnsafeOrigin).protocol,
fileHost: config.fileHost || undefined,
fileHost: config.fileHost? new URL(config.fileHost).origin : undefined,
NO_SANDBOX: NO_SANDBOX,
httpSafePort: httpSafePort,
websocketPort: config.websocketPort,

View File

@ -107,6 +107,10 @@ HK.authenticateNetfluxSession = function (Env, netfluxId, unsafeKey) {
var user = Env.netfluxUsers[netfluxId] = Env.netfluxUsers[netfluxId] || {};
user[unsafeKey] = +new Date();
};
HK.unauthenticateNetfluxSession = function (Env, netfluxId, unsafeKey) {
var user = Env.netfluxUsers[netfluxId] = Env.netfluxUsers[netfluxId] || {};
delete user[unsafeKey];
};
HK.closeNetfluxSession = function (Env, netfluxId) {
delete Env.netfluxUsers[netfluxId];
@ -804,7 +808,7 @@ const handleGetHistoryRange = function (Env, Server, seq, userId, parsed) {
if (hash === untilHash || untilHash === 'NONE') { found = true; }
let then = hash === oldestKnownHash ? abort : readMore;
if (found) {
Server.send(userId, [0, HISTORY_KEEPER_ID, 'MSG', userId,
return void Server.send(userId, [0, HISTORY_KEEPER_ID, 'MSG', userId,
JSON.stringify(['HISTORY_RANGE', txid, parsed])], then);
}
return void readMore();

View File

@ -72,6 +72,7 @@ const AUTHENTICATED_USER_SCOPED = {
REMOVE_PINS: Pinning.removePins,
TRIM_PINS: Pinning.trimPins,
COOKIE: Core.haveACookie,
DESTROY: () => {}
};
var isAuthenticatedCall = function (call) {
@ -190,6 +191,11 @@ var rpc = function (Env, Server, userId, data, respond) {
if (command === 'COOKIE' && !hadSession && Env.logIP) {
Env.Log.info('NEW_RPC_SESSION', {userId: userId, publicKey: publicKey});
}
if (command === "DESTROY") {
HK.unauthenticateNetfluxSession(Env, userId, publicKey);
return; // No need to respond, user will close the session
}
HK.authenticateNetfluxSession(Env, userId, publicKey);
return void handleAuthenticatedMessage(Env, publicKey, msg, respond, Server);
});

View File

@ -264,6 +264,8 @@ var factory = function (Util, Nacl) {
clearTimeout(to);
});
ctx.send('DESTROY', "", function () {});
// remove the ctx from the network's stack
var idx = networkContext.authenticated.indexOf(ctx);
if (idx === -1) { return; }

View File

@ -25,6 +25,7 @@ const factory = (Sortify, UserObject, ProxyManager,
const Saferphore = Util.Saferphore;
var onReadyEvt = Util.mkEvent(true);
var onCacheReadyEvt = Util.mkEvent(true);
var onDriveReadyEvt = Util.mkEvent(true);
var onPadRejectedEvt = Util.mkEvent(true);
const setCustomize = data => {
@ -1608,7 +1609,7 @@ const factory = (Sortify, UserObject, ProxyManager,
if (!Array.isArray(allowed)) { return void cb('ERESTRICTED'); }
onPadRejectedEvt.fire();
onReadyEvt.reg(() => {
onDriveReadyEvt.reg(() => {
// There is an allow list: check if we can authenticate
if (!store.loggedIn || !store.proxy.edPublic) { return void cb('ERESTRICTED'); }
@ -2570,6 +2571,7 @@ const factory = (Sortify, UserObject, ProxyManager,
cacheCb(store.cacheReturned || store.returned);
});
onDriveReady(() => {
onDriveReadyEvt.fire();
cb(store.returned);
});

View File

@ -24,7 +24,16 @@ const factory = (Crypto) => {
msg: data.msg,
uid: data.uid,
};
chan.sendMsg(JSON.stringify(obj), cb);
if (obj.msg === 'ISAVE') {
ctx.pending[data.uid] = true;
}
chan.sendMsg(JSON.stringify(obj), obj => {
if (!ctx.pending[data.uid]) {
return void setTimeout(cb, 1000);
}
delete ctx.pending[data.uid];
cb(obj);
});
ctx.emit('MESSAGE', obj, chan.clients.filter(function (cl) {
return cl !== client;
}));
@ -90,6 +99,9 @@ const factory = (Crypto) => {
var parsed;
try {
parsed = JSON.parse(msg);
if (parsed.msg === "ISAVE") {
delete ctx.pending[parsed.uid];
}
ctx.emit('MESSAGE', parsed, chan.clients);
} catch (e) { console.error(e); }
});
@ -176,6 +188,7 @@ const factory = (Crypto) => {
store: cfg.store,
emit: emit,
channels: {},
pending: {}, // prevent ISAVE race condition
clients: {}
};

View File

@ -107,6 +107,7 @@ const factory = (Util, Hash, Constants, Realtime, ProxyManager,
try { team.roster.stop(); } catch (e) {}
team.proxy = {};
team.stopped = true;
team?.rpc?.destroy();
delete ctx.teams[teamId];
delete ctx.cache[teamId];
delete ctx.store.proxy.teams[teamId];

View File

@ -78,6 +78,7 @@ let start = (cfg: StoreConfig):void => {
Store,
Account,
Mailbox,
Messenger,
Badge
].forEach(dep => {
if (typeof(dep.setCustomize) === "function") {

View File

@ -172,6 +172,10 @@
text-align:center;
flex-shrink: 0;
}
.tui-full-calendar-calendar-dot {
margin-right: 10px;
top: 0;
}
.tui-full-calendar-popup-detail-item {
display: flex;
margin-bottom: 0.3rem;
@ -195,7 +199,6 @@
}
}
a {
margin:0.1rem;
border-radius: @variables_radius;
color: @cryptpad_color_link;
text-decoration: underline;
@ -314,6 +317,9 @@
font-size: inherit;
line-height: inherit;
}
* {
box-sizing: content-box;
}
}
.CodeMirror-placeholder {
color: @cp_forms-placeholder;

View File

@ -2387,6 +2387,23 @@ APP.recurrenceRule = {
});
}
var privateData = metadataMgr.getPrivateData();
$el.find('.event-description').click(e => {
if (!e.target) { return; }
var $t = $(e.target);
if (!$t.is('a') && !$t.parents('a').length) { return; }
e.preventDefault();
var $a = $t.is('a') ? $t : $t.parents('a').first();
var href = $a.attr('href');
if (/^#/.test(href)) { return; }
if (/^\/[^\/]/.test(href)) {
href = privateData.origin + href;
return void common.openURL(href);
}
common.openUnsafeURL(href);
});
console.error($el.find('.event-description'), $el);
var $section = $el.find('.tui-full-calendar-section-button');
var ev = APP.editModalData;
var data = ev.schedule || {};

View File

@ -1651,6 +1651,27 @@ define([
});
});
// confirm that POST requests to the `/upload-blob` endpoint
// return something other than a 404, which would probably indicate
// a reverse proxy misconfiguration
assert(function (cb, msg) {
msg.appendChild(h('span', [
`The server returned a 404 error when attempting to reach the `,
h('code', `/upload-blob`),
` endpoint. This can be caused by an incorrectly configured reverse proxy.`,
]));
fetch('/upload-blob', {
method: 'POST',
}).then(res => {
console.log({ upload_fetch_response: res });
cb(res.status !== 404);
}).catch(err => {
console.error(err);
cb(false);
});
});
var row = function (cells) {
return h('tr', cells.map(function (cell) {
return h('td', cell);

View File

@ -80,7 +80,9 @@ define([
var keys = [];
nThen(function (waitFor) {
// Not logged in? check for temp RPC keys
if (!LocalStore.isLoggedIn() && Env?.returned?.tempKeys) {
const anon = !LocalStore.isLoggedIn()
|| common.neverDrive;
if (anon && Env?.returned?.tempKeys) {
keys.push(Env.returned.tempKeys);
return;
}
@ -2672,6 +2674,7 @@ define([
Messages,
AppConfig
};
common.neverDrive = rdyCfg.neverDrive;
common.userHash = userHash || LocalStore.getUserHash();
// FIXME Backward compatibility

View File

@ -2163,7 +2163,7 @@ define([
url: url,
permissions: {
download: dc?.permissions?.download || false,
print: dc?.permissions?.print || true,
print: dc?.permissions?.print !== false,
protect: file.type === 'xlsx',
}
},

View File

@ -670,6 +670,10 @@ define([
UI.removeLoadingScreen(emitResize);
if (integrationChannel) {
integrationChannel.event('EV_INTEGRATION_READY');
}
if (AppConfig.textAnalyzer && textContentGetter) {
AppConfig.textAnalyzer(textContentGetter, privateDat.channel);
}

View File

@ -92,7 +92,7 @@ define([
if (state.me) { return; } // I have the lock: abort
if (state.other && state.other !== data.uid) { return; } // someone else has the lock
// If state.other === data.uid ==> save failed and someone else tries again
if (!state.changed) { return; }
if (!state.changed && state.other !== data.uid) { return; }
// If !state.other: nobody has the lock, give them
state.other = data.uid;
state.lastTmp = +new Date();
@ -103,6 +103,7 @@ define([
setStateChanged(false);
saveTo = setTimeout(function () {
// They weren't able to save in time, try ourselves
setStateChanged(true);
var id = state.other;
state.other = false;
save(id);
@ -151,7 +152,7 @@ define([
// is already saving
requestSave = function (id, cb) {
if (state.other || state.me) { return void cb(false); } // save in progress
debug('Integration send ISAVE');
debug('Integration send ISAVE', id);
alreadySaved = false; // someone may have saved while we were waiting for our callback
execCommand('SEND', {
msg: 'ISAVE',

View File

@ -609,7 +609,7 @@
"friendRequest_later": "Tentukan nanti",
"friendRequest_accept": "Terima (Enter)",
"profile_addDescription": "Tambahkan deskripsi",
"profile_addLink": "Tambahkan tautan ke situs web Anda",
"profile_addLink": "Tautan ke situs web Anda",
"notification_padShared": "{0} telah membagikan dokumen dengan Anda: <b>{1}</b>",
"notification_folderShared": "{0} telah membagikan folder dengan Anda: <b>{1}</b>",
"share_filterFriend": "Cari berdasarkan nama",
@ -622,7 +622,7 @@
"footer_donate": "Berdonasi",
"drive_active7Days": "7 hari terakhir",
"drive_active28Days": "4 minggu terakhir",
"profile_editDescription": "Sunting deskripsi Anda",
"profile_editDescription": "Deskripsi profil",
"notification_fileShared": "{0} telah membagikan berkas dengan Anda: <b>{1}</b>",
"admin_supportAddError": "Kunci privat tidak absah",
"password_info": "Dokumen yang Anda buka sudah tidak ada atau dilindungi dengan kata sandi baru. Masukkan kata sandi yang benar untuk mengakses kontennya.",
@ -1091,7 +1091,7 @@
"mediatag_notReady": "Silakan selesaikan unduhan",
"addOptionalPassword": "Tambahkan kata sandi (opsional)",
"broadcast_defaultLanguage": "Gunakan bahasa ini sebagai cadangan",
"calendar_errorNoCalendar": "Tidak ada kalender dapat disunting yang dipilih",
"calendar_errorNoCalendar": "Tidak ada kalender yang tersedia",
"calendar_import": "Tambahkan ke kalender saya",
"calendar_dateTimeRange": "{0} {1} - {2}",
"admin_supportPrivTitle": "Kunci pribadi kotak surat bantuan",
@ -1174,7 +1174,7 @@
"calendar_more": "{0} lagi",
"form_invalidQuestion": "Pertanyaan {0}",
"mdToolbar_embed": "Sematkan berkas",
"fm_link_invalid": "URL tidak valid",
"fm_link_invalid": "Silakan sediakan URL yang valid",
"calendar_str_monthly": "{0} bulan",
"comments_reply": "Balas",
"comments_resolve": "Selesaikan",
@ -1780,5 +1780,66 @@
"admin_onboardingNamePlaceholder": "Judul server",
"admin_onboardingDescPlaceholder": "Teks deskripsi server",
"admin_onboardingOptionsHint": "Silakan pilih opsi sesuai untuk server Anda.<br>Pengaturan ini dapat diubah lagi dalam panel admin.",
"install_notes": "<ul class=\"cp-notes-list\"><li>Buat akun administrator Anda yang pertama di laman ini. Administrator mengelola pengaturan server termasuk kuota penyimpanan dan memiliki akses ke peralatan moderasi.</li><li>Kata sandi Anda adalah kunci rahasia yang mengenkripsi semua dokumen dan hak administrator Anda di server ini.<span class=\"red\">Jika Anda kehilangan kata sandi tersebut, kami tidak dapat memulihkan data Anda.</span></li><li>Jika Anda menggunakan komputer terbagi, <span class=\"red\">jangan lupa untuk keluar dari akun</span> setelah Anda selesai. Hanya menutup jendela peramban membuat akun Anda rentan.</li></ul>"
"install_notes": "<ul class=\"cp-notes-list\"><li>Buat akun administrator Anda yang pertama di laman ini. Administrator mengelola pengaturan server termasuk kuota penyimpanan dan memiliki akses ke peralatan moderasi.</li><li>Kata sandi Anda adalah kunci rahasia yang mengenkripsi semua dokumen dan hak administrator Anda di server ini.<span class=\"red\">Jika Anda kehilangan kata sandi tersebut, kami tidak dapat memulihkan data Anda.</span></li><li>Jika Anda menggunakan komputer terbagi, <span class=\"red\">jangan lupa untuk keluar dari akun</span> setelah Anda selesai. Hanya menutup jendela peramban membuat akun Anda rentan.</li></ul>",
"form_passwordWarning": "Diingat bahwa kata sandi Form hanya dapat diatur sekarang pada waktu pembuatan dan tidak dapat diubah nanti.",
"admin_addKeyLabel": "Tambahkan admin menggunakan kunci publiknya",
"admin_documentsDeletionTitle": "Arsipkan beberapa dokumen",
"admin_addAdminsHint": "Tambahkan administrator dari kunci publiknya atau dari daftar kontak Anda",
"admin_listConfirm": "Apakah Anda yakin ingin menghapus hak admin dari pengguna ini?",
"skipLink": "Lewati ke konten utama",
"toggleArrows": "Tombol panah untuk memindahkan item",
"oo_couldNotConvertDocument": "Konversi dokumen gagal. Saat ini format Microsoft Office (.docx, .xlsx, .pptx) memberikan hasil terbaik untuk pengimporan dan pengeksporan.",
"admin_documentsDeletionHint": "Arsipkan daftar dokumen menggunakan id-nya (satu id dokumen per baris)",
"fm_restoreMultipleDialog": "Apakah Anda yakin ingin memulihkan {0} berkas dan/atau folder ke tempat sebelumnya?",
"calendar_show": "Tampilkan kalender",
"calendar_hide": "Sembunyikan kalender",
"oo_unstableMigrationWarning": "Impor dan Ekspor beberapa format OpenDocument (.odt, .odp) saat ini tidak stabil. Kami menyarankan menggunakan format lain jika dimungkinkan. CryptPad akan mencoba konversi sebaik mungkin.",
"admin_logoSize_error": "Ukuran logo terlalu besar",
"error_limit": "Silakan masukkan angka yang valid",
"form_answerType_error": "Silakan pilih cara menjawab formulir",
"error_positiveNumber": "Silakan masukkan angka positif",
"admin_cat_admins": "Administrator",
"admin_admin": "Admin",
"admin_listAdminsTitle": "Administrator saat ini",
"admin_listAdminsHint": "Tampilkan dan hapus administrator",
"admin_addAdminsTitle": "Tambahkan administrator",
"admin_addAdminsAdd": "Promosikan kontak sebagai admin",
"admin_errorAddKeyLabel": "Tambahkan kunci publik yang valid",
"admin_errorAddAdmins": "Pilih kontak untuk dipromosikan sebagai admin",
"admin_listName": "Nama admin",
"admin_listKey": "Kunci admin",
"admin_listAction": "Hapus hak admin",
"admin_listHardcoded": "Admin ditambahkan ke config.js. Hanya dapat dihapus dengan menyunting berkas konfig.",
"addItemBottom": "Tambahkan kartu ke bawah papan",
"addItemTop": "Tambahkan kartu ke atas papan",
"moveItemLeft": "Pindahkan item ke kiri",
"moveItemRight": "Pindahkan item ke kanan",
"kanban_moveBoardLeft": "Pindahkan papan ke kiri",
"kanban_moveBoardRight": "Pindahkan papan ke kanan",
"moveItemUp": "Pindahkan item ke atas",
"moveItemDown": "Pindahkan item ke bawah",
"toggleDrag": "Tarik untuk memindahkan item",
"profile_remove_avatar": "Hapus avatar ini",
"team_autoTrim": "Memangkas riwayat drive tim... Silakan tunggu.",
"admin_mfa_confirm_enable": "Apakah Anda yakin ingin mengaktifkan Autentikasi Multi-Faktor?",
"admin_mfa_confirm_disable": "Apakah Anda yakin ingin menonaktifkan Autentikasi Multi-Faktor?",
"badges_moderator": "Bantuan dan moderasi",
"badges_admin": "Administrator",
"badges_premium": "Pelanggan",
"badges_error": "Kesalahan validasi",
"profile_badges": "Lencana",
"show_password": "Tampilkan kata sandi",
"hide_password": "Sembunyikan kata sandi",
"page_previous": "Halaman sebelumnya",
"page_next": "Halaman berikutnya",
"contact_mastodon": "Mastodon",
"contact_forum": "Forum",
"settings_profileAvatarLabel": "Avatar",
"settings_profileHeaderTitle": "Informasi profil",
"settings_profileHeaderHint": "Pilih apa saja tentang akun Anda yang dapat dilihat oleh orang lain",
"toolbar_text_tools": "Peralatan teks",
"toolbar_show_text_tools": "Tampilkan peralatan teks",
"toolbar_hide_text_tools": "Sembunyikan peralatan teks",
"fc_open_formaud": "Buka (sebagai pengaudit)",
"help_close_button": "Tutup notifikasi bantuan"
}

View File

@ -1825,5 +1825,6 @@
"admin_addAdminsHint": "Aggiungi amministratori/trici tramite la loro chiave pubblica o dalla tua lista contatti",
"admin_addAdminsAdd": "Promuovi un contatto ad amministratore/trice",
"toggleArrows": "Pulsanti freccia per spostare gli elementi",
"oo_unstableMigrationWarning": "L'importazione e l'esportazione di alcuni formati OpenDocument (.odt, .odp) è attualmente instabile. Si consiglia di utilizzare altri formati quando possibile. CryptPad tenterà ora una conversione."
"oo_unstableMigrationWarning": "L'importazione e l'esportazione di alcuni formati OpenDocument (.odt, .odp) è attualmente instabile. Si consiglia di utilizzare altri formati quando possibile. CryptPad tenterà ora una conversione.",
"settings_profileHeaderTitle": "Informazioni del profilo"
}

View File

@ -113,7 +113,7 @@
"settings_save": "保存",
"profile_viewMyProfile": "自分のプロフィールを表示",
"clickToEdit": "クリックして編集",
"profile_addLink": "あなたのウェブサイトへのリンクを追加",
"profile_addLink": "あなたのウェブサイトへのリンク",
"shareSuccess": "リンクをクリップボードにコピーしました",
"shareButton": "共有",
"login_hashing": "パスワードをハッシュ化しています。この処理には時間がかかる場合があります。",
@ -144,7 +144,7 @@
"saved": "保存済",
"error": "エラー",
"deleted": "削除しました",
"profile_editDescription": "説明文を編集",
"profile_editDescription": "プロフィールの説明文",
"profile_addDescription": "説明文を追加",
"profileButton": "プロフィール",
"profile_upload": " 新しいアバターをアップロード",
@ -1818,5 +1818,27 @@
"admin_errorAddKeyLabel": "正しい公開鍵を追加してください",
"skipLink": "メインの内容にスキップ",
"addItemTop": "カードをボードの最上部に追加",
"profile_remove_avatar": "このアバターを削除"
"profile_remove_avatar": "このアバターを削除",
"oo_couldNotConvertDocument": "ドキュメントの変換に失敗しました。現在はMicrosoft Officeのフォーマット.docx, .xlsx, .pptxがインポートとエクスポートに最もよく対応しています。",
"oo_unstableMigrationWarning": "現在、一部のOpenDocumentのフォーマット.odt, .odpのインポートとエクスポートは不安定です。可能な場合は他のフォーマットを使用することを推奨します。これから、可能な範囲での変換を試みます。",
"badges_moderator": "サポートとモデレート",
"badges_admin": "管理者",
"badges_premium": "定額利用のユーザー",
"badges_error": "検証エラー",
"profile_badges": "バッジ",
"show_password": "パスワードを表示",
"hide_password": "パスワードを表示しない",
"page_previous": "前のページ",
"page_next": "次のページ",
"settings_profileHeaderHint": "アカウントの画面に表示するものを選択してください",
"contact_mastodon": "Mastodon",
"contact_forum": "フォーラム",
"settings_profileAvatarLabel": "アバター",
"settings_profileHeaderTitle": "プロフィールの情報",
"toolbar_text_tools": "テキストツール",
"toolbar_show_text_tools": "テキストツールを表示",
"toolbar_hide_text_tools": "テキストツールを表示しない",
"help_close_button": "ヘルプの通知を閉じる",
"admin_documentsDeletionTitle": "複数のドキュメントをアーカイブ",
"admin_documentsDeletionHint": "IDをリストの形式で指定してドキュメントをアーカイブ1行に1つのドキュメントを指定してください"
}

View File

@ -899,8 +899,8 @@
"isContact": "{0} - один из Ваших контактов",
"profile_friendRequestSent": "Запрос на контакт ожидает рассмотрения ...",
"profile_info": "Другие пользователи могут найти ваш профиль через ваш аватар в списках пользователей документов.",
"profile_addLink": "Добавьте ссылку на свой вебсайт",
"profile_editDescription": "Изменить описание",
"profile_addLink": "Ссылка на Ваш вебсайт",
"profile_editDescription": "Описание профиля",
"profile_addDescription": "Добавить описание",
"notifications_empty": "Нет доступных уведомлений",
"friendRequest_notification": "<b>{0}</b> отправил(а) Вам запрос на контакт",
@ -1820,5 +1820,26 @@
"moveItemDown": "Переместить элемент ниже",
"profile_remove_avatar": "Удалить этот аватар",
"oo_couldNotConvertDocument": "Не удалось сконвертировать документ. Обратите внимание, что форматы Microsoft Office (.docx, .xlsx, .pptx) в настоящее время дают наилучшие результаты для импорта и экспорта.",
"oo_unstableMigrationWarning": "Импорт и экспорт некоторых форматов OpenDocument (.odt, .odp) в настоящее время нестабильны. Мы рекомендуем использовать другие форматы, где это возможно. Сейчас CryptPad попытается выполнить преобразование как можно лучше."
"oo_unstableMigrationWarning": "Импорт и экспорт некоторых форматов OpenDocument (.odt, .odp) в настоящее время нестабильны. Мы рекомендуем использовать другие форматы, где это возможно. Сейчас CryptPad попытается выполнить преобразование как можно лучше.",
"badges_moderator": "Поддержка и модерация",
"badges_admin": "Администратор",
"badges_premium": "Подписчик",
"badges_error": "Ошибка валидации",
"profile_badges": "Значок",
"show_password": "Показать пароль",
"hide_password": "Скрыть пароль",
"page_previous": "Предыдущая страница",
"page_next": "Следующая страница",
"settings_profileHeaderHint": "Выберите, что другие пользователи видят о Вашем аккаунте",
"contact_mastodon": "Mastodon",
"contact_forum": "Форум",
"settings_profileAvatarLabel": "Аватар",
"settings_profileHeaderTitle": "Информация профиля",
"toolbar_text_tools": "Инструменты для работы с текстом",
"toolbar_show_text_tools": "Показать текстовые инструменты",
"toolbar_hide_text_tools": "Скрыть текстовые инструменты",
"help_close_button": "Закрыть уведомление о помощи",
"fc_open_formaud": "Открыть (как аудитор)",
"admin_documentsDeletionTitle": "Архивировать несколько документов",
"admin_documentsDeletionHint": "Архивировать несколько документов, используя их идентификаторы (по одному идентификатору документа в строке)"
}

View File

@ -1837,5 +1837,9 @@
"settings_profileAvatarLabel": "头像",
"toolbar_text_tools": "文本工具",
"toolbar_show_text_tools": "显示文本工具",
"toolbar_hide_text_tools": "隐藏文本工具"
"toolbar_hide_text_tools": "隐藏文本工具",
"fc_open_formaud": "打开(作为审计者)",
"help_close_button": "关闭帮助通知",
"admin_documentsDeletionTitle": "归档多个文档",
"admin_documentsDeletionHint": "使用文档 ID 归档文档列表(每行一个文档 ID"
}

File diff suppressed because one or more lines are too long

View File

@ -63,9 +63,11 @@ define([
var onDrawioInit = function() {
drawIoInitalized = true;
var readOnly = framework.isReadOnly() || framework.isLocked();
var grid = readOnly ? 0 : 1;
lastContent.mxfile.diagram.mxGraphModel._grid = grid;
if (lastContent?.mxfile?.diagram?.mxGraphModel) {
let readOnly = framework.isReadOnly() || framework.isLocked();
let grid = readOnly ? 0 : 1;
lastContent.mxfile.diagram.mxGraphModel._grid = grid;
}
var xmlStr = DiagramUtil.jsonContentAsXML(lastContent);
postMessageToDrawio({
action: 'load',

View File

@ -191,9 +191,6 @@
position: relative;
.cp-markdown-toggle-button {
.markdown-toolbar-button-style();
&.cp-toolbar-button-active {
//background-color: transparent !important;
}
}
}
@ -869,7 +866,6 @@
}
.cp-markdown-toolbar {
display: block;
padding: 0.1rem 0;
border-radius: @variables_radius 0;
width: 100%;
background-color: transparent;

View File

@ -177,12 +177,6 @@
background-color: transparent;
color: @cp_kanban-fg;
border-radius: @variables_radius @variables_radius 0px 0px;
button {
&:hover {
background-color: @cp_kanban-fg;
color: @cp_kanban-conflict-bg;
}
}
.btn {
outline: 0;
border-radius: @variables_radius;

View File

@ -447,6 +447,7 @@ define([
APP.getEdPublic = function () {
var metadataMgr = APP.common.getMetadataMgr();
var privateData = metadataMgr.getPrivateData();
const data = APP._lastUpdate;
var url = Hash.getPublicSigningKeyString(privateData.origin, data.name, data.edPublic);
Clipboard.copy(url, (err) => {
if (!err) { UI.log(Messages.genericCopySuccess); }

View File

@ -326,6 +326,9 @@
font-size: inherit;
line-height: inherit;
}
* {
box-sizing: content-box;
}
}
.cp-markdown-toggle-button {
.markdown-toolbar-button-style();