diff --git a/admin/src/pages/PadPage.tsx b/admin/src/pages/PadPage.tsx index 2b8ba06d119..844a32b8007 100644 --- a/admin/src/pages/PadPage.tsx +++ b/admin/src/pages/PadPage.tsx @@ -410,7 +410,7 @@ export const PadPage = () => { diff --git a/src/static/js/pad_userlist.ts b/src/static/js/pad_userlist.ts index d3ee825276c..c34acccff96 100644 --- a/src/static/js/pad_userlist.ts +++ b/src/static/js/pad_userlist.ts @@ -23,6 +23,14 @@ const chat = require('./chat').chat; import html10n from './vendors/html10n'; let myUserInfo = {}; +const decodePadSegment = (segment: string): string => { + try { + return decodeURIComponent(segment); + } catch { + return segment; + } +}; + let colorPickerOpen = false; let colorPickerSetup = false; @@ -557,7 +565,7 @@ const paduserlist = (() => { if (localStorage.getItem('recentPads') != null) { const recentPadsList = JSON.parse(localStorage.getItem('recentPads')); const pathSegments = window.location.pathname.split('/'); - const padName = pathSegments[pathSegments.length - 1]; + const padName = decodePadSegment(pathSegments[pathSegments.length - 1]); const existingPad = recentPadsList.find((pad) => pad.name === padName); if (existingPad) { existingPad.members = online; diff --git a/src/static/skins/colibris/index.js b/src/static/skins/colibris/index.js index f36edf84180..e48e07e021b 100644 --- a/src/static/skins/colibris/index.js +++ b/src/static/skins/colibris/index.js @@ -1,5 +1,13 @@ 'use strict'; +const decodePadName = (name) => { + try { + return decodeURIComponent(name); + } catch { + return name; + } +}; + window.addEventListener('pageshow', (event) => { if (event.persisted) { if (document.readyState === 'complete' || document.readyState === 'interactive') { @@ -37,6 +45,13 @@ window.customStart = () => { recentPadListData = JSON.parse(recentPadsFromLocalStorage); } + // Normalize older entries that stored encoded names (e.g. Test%2F123). + recentPadListData = recentPadListData.map((pad) => ({ + ...pad, + name: decodePadName(String(pad.name ?? '')), + })); + localStorage.setItem('recentPads', JSON.stringify(recentPadListData)); + // Remove duplicates based on pad name and sort by timestamp recentPadListData = recentPadListData.filter( (pad, index, self) => index === self.findIndex((p) => p.name === pad.name) @@ -70,7 +85,7 @@ window.customStart = () => { li.style.cursor = 'pointer'; li.className = 'recent-pad'; - const padPath = `${window.location.href}p/${pad.name}`; + const padPath = `${window.location.href}p/${encodeURIComponent(pad.name)}`; const link = document.createElement('a'); link.style.textDecoration = 'none'; diff --git a/src/static/skins/colibris/pad.js b/src/static/skins/colibris/pad.js index 1e7a85b3faa..21b48a70329 100644 --- a/src/static/skins/colibris/pad.js +++ b/src/static/skins/colibris/pad.js @@ -1,6 +1,13 @@ 'use strict'; const MAX_PADS_IN_HISTORY = 3; +const decodePadSegment = (segment) => { + try { + return decodeURIComponent(segment); + } catch { + return segment; + } +}; window.customStart = () => { $('#pad_title').show(); @@ -8,7 +15,7 @@ window.customStart = () => { $('.buttonicon').on('mouseup', function () { $(this).parent().removeClass('pressed'); }); const pathSegments = window.location.pathname.split('/'); - const padName = pathSegments[pathSegments.length - 1]; + const padName = decodePadSegment(pathSegments[pathSegments.length - 1]); const recentPads = localStorage.getItem('recentPads'); if (recentPads == null) { localStorage.setItem('recentPads', JSON.stringify([]));