From 35205a9309629603c1df0b2760aa5aa86ff2a924 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Wed, 21 Apr 2021 17:09:56 +0100 Subject: [PATCH 01/54] Include news account --- blog.py | 12 +++++++++--- theme.py | 4 +++- utils.py | 16 +++++++++++----- webapp_moderation.py | 4 +++- webapp_search.py | 4 ++++ 5 files changed, 30 insertions(+), 10 deletions(-) diff --git a/blog.py b/blog.py index 9235b8e22..f2651b8db 100644 --- a/blog.py +++ b/blog.py @@ -619,7 +619,9 @@ def _noOfBlogAccounts(baseDir: str) -> int: for acct in dirs: if '@' not in acct: continue - if 'inbox@' in acct: + if acct.startswith('inbox@'): + continue + elif acct.startswith('news@'): continue accountDir = os.path.join(baseDir + '/accounts', acct) blogsIndex = accountDir + '/tlblogs.index' @@ -636,7 +638,9 @@ def _singleBlogAccountNickname(baseDir: str) -> str: for acct in dirs: if '@' not in acct: continue - if 'inbox@' in acct: + if acct.startswith('inbox@'): + continue + elif acct.startswith('news@'): continue accountDir = os.path.join(baseDir + '/accounts', acct) blogsIndex = accountDir + '/tlblogs.index' @@ -676,7 +680,9 @@ def htmlBlogView(authorized: bool, for acct in dirs: if '@' not in acct: continue - if 'inbox@' in acct: + if acct.startswith('inbox@'): + continue + elif acct.startswith('news@'): continue accountDir = os.path.join(baseDir + '/accounts', acct) blogsIndex = accountDir + '/tlblogs.index' diff --git a/theme.py b/theme.py index 3a8d9c897..4aec87b13 100644 --- a/theme.py +++ b/theme.py @@ -551,7 +551,9 @@ def _setThemeImages(baseDir: str, name: str) -> None: for acct in dirs: if '@' not in acct: continue - if 'inbox@' in acct: + if acct.startswith('inbox@'): + continue + elif acct.startswith('news@'): continue accountDir = \ os.path.join(baseDir + '/accounts', acct) diff --git a/utils.py b/utils.py index d1addc920..dce31f502 100644 --- a/utils.py +++ b/utils.py @@ -388,7 +388,9 @@ def getFollowersOfPerson(baseDir: str, for subdir, dirs, files in os.walk(baseDir + '/accounts'): for account in dirs: filename = os.path.join(subdir, account) + '/' + followFile - if account == handle or account.startswith('inbox@'): + if account == handle or \ + account.startswith('inbox@') or \ + account.startswith('news@'): continue if not os.path.isfile(filename): continue @@ -1057,7 +1059,7 @@ def clearFromPostCaches(baseDir: str, recentPostsCache: {}, for acct in dirs: if '@' not in acct: continue - if 'inbox@' in acct: + if acct.startswith('inbox@'): continue cacheDir = os.path.join(baseDir + '/accounts', acct) postFilename = cacheDir + filename @@ -1405,8 +1407,11 @@ def noOfAccounts(baseDir: str) -> bool: for subdir, dirs, files in os.walk(baseDir + '/accounts'): for account in dirs: if '@' in account: - if not account.startswith('inbox@'): - accountCtr += 1 + if account.startswith('inbox@'): + continue + elif account.startswith('news@'): + continue + accountCtr += 1 break return accountCtr @@ -1420,7 +1425,8 @@ def noOfActiveAccountsMonthly(baseDir: str, months: int) -> bool: for subdir, dirs, files in os.walk(baseDir + '/accounts'): for account in dirs: if '@' in account: - if not account.startswith('inbox@'): + if not account.startswith('inbox@') and \ + not account.startswith('news@'): lastUsedFilename = \ baseDir + '/accounts/' + account + '/.lastUsed' if os.path.isfile(lastUsedFilename): diff --git a/webapp_moderation.py b/webapp_moderation.py index 585c8f3cc..a8e90fdb9 100644 --- a/webapp_moderation.py +++ b/webapp_moderation.py @@ -270,7 +270,9 @@ def htmlModerationInfo(cssCache: {}, translate: {}, for acct in dirs: if '@' not in acct: continue - if 'inbox@' in acct or 'news@' in acct: + if acct.startswith('inbox@'): + continue + elif acct.startswith('news@'): continue accounts.append(acct) break diff --git a/webapp_search.py b/webapp_search.py index d87e92021..16f548266 100644 --- a/webapp_search.py +++ b/webapp_search.py @@ -404,6 +404,8 @@ def htmlSkillsSearch(actor: str, continue if f.startswith('inbox@'): continue + elif f.startswith('news@'): + continue actorFilename = os.path.join(subdir, f) actorJson = loadJson(actorFilename) if actorJson: @@ -439,6 +441,8 @@ def htmlSkillsSearch(actor: str, continue if f.startswith('inbox@'): continue + elif f.startswith('news@'): + continue actorFilename = os.path.join(subdir, f) cachedActorJson = loadJson(actorFilename) if cachedActorJson: From eaccc3f2e5a548f3d9ea948c1b3b4dea63cce4bd Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Wed, 21 Apr 2021 17:35:40 +0100 Subject: [PATCH 02/54] Update code of conduct --- code-of-conduct.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/code-of-conduct.md b/code-of-conduct.md index 01c77166c..73e4b2a1e 100644 --- a/code-of-conduct.md +++ b/code-of-conduct.md @@ -26,6 +26,12 @@ No stalking, unwanted personal attention, or unwelcome revealing or speculating In cases of sincere, good-faith curiosity about someone’s experience or identity, ask politely in a manner such that they will feel free to decline the request. +## No non-consenting research + +People contributing to, or maintaining, this project should not be treated as research subjects in academic studies without their prior written consent. If anthropological, security, or other types of research are being conducted upon contributors then they must be made aware of this and formally agree to it taking place. + +Publishing software under an AGPL license does not imply consent to become a research subject. + ## No hostile communication No insults, harassment (sexual or otherwise), condescension, ad hominem, threats, or other intimidation. Claims that such communications were intended as "ironic" or humerous will also be considered a code of conduct violation. From dcb5e4d2ddf28ddbcf5a6169cf05a935d461a749 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Wed, 21 Apr 2021 21:01:09 +0100 Subject: [PATCH 03/54] Set default bio --- webapp_welcome_profile.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/webapp_welcome_profile.py b/webapp_welcome_profile.py index 7dde5d9ce..e3d164d9f 100644 --- a/webapp_welcome_profile.py +++ b/webapp_welcome_profile.py @@ -107,6 +107,8 @@ def htmlWelcomeProfile(baseDir: str, nickname: str, domain: str, bioStr = \ actorJson['summary'].replace('

', '').replace('

', '') + if not bioStr: + bioStr = translate['Your bio'] profileForm += '
\n' profileForm += ' \n' + editProfileForm += \ + '
\n' + idx = 'Direct messages are always allowed from these instances.' + editProfileForm += \ + '
\n' + editProfileForm += \ + ' \n' + editProfileForm += \ '
\n' From 01ae3221391a3ad51dad9a670b3ab7278ec4c332 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 22 Apr 2021 11:54:49 +0100 Subject: [PATCH 06/54] Boolean return --- utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils.py b/utils.py index 170920146..2542e90a0 100644 --- a/utils.py +++ b/utils.py @@ -2207,7 +2207,7 @@ def loadTranslationsFromFile(baseDir: str, language: str) -> ({}, str): def dmAllowedFromDomain(baseDir: str, nickname: str, domain: str, - sendingActorDomain: str): + sendingActorDomain: str) -> bool: """When a DM is received and the .followDMs flag file exists Then optionally some domains can be specified as allowed, regardless of individual follows. From 5343c38ff28005d8aa11a5881c6c05458a2e4da0 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 22 Apr 2021 12:51:19 +0100 Subject: [PATCH 07/54] Key shortcuts --- webapp_calendar.py | 6 +++++- webapp_login.py | 2 +- webapp_person_options.py | 2 +- webapp_profile.py | 21 +++++++++++++++++++-- webapp_search.py | 2 +- webapp_timeline.py | 20 ++++++++++++++++++-- webapp_utils.py | 8 ++++++-- 7 files changed, 51 insertions(+), 10 deletions(-) diff --git a/webapp_calendar.py b/webapp_calendar.py index 8ba1500cc..4a5c7abb3 100644 --- a/webapp_calendar.py +++ b/webapp_calendar.py @@ -456,7 +456,11 @@ def htmlCalendar(personCache: {}, cssCache: {}, translate: {}, htmlHideFromScreenReader('←') + ' ' + translate['Previous month'] navLinks[prevMonthStr] = calActor + '/calendar?year=' + str(prevYear) + \ '?month=' + str(prevMonthNumber) + # TODO + navAccessKeys = { + } screenReaderCal = \ - htmlKeyboardNavigation(textModeBanner, navLinks, monthName) + htmlKeyboardNavigation(textModeBanner, navLinks, navAccessKeys, + monthName) return headerStr + screenReaderCal + calendarStr + htmlFooter() diff --git a/webapp_login.py b/webapp_login.py index e488d5f46..9e5fa6206 100644 --- a/webapp_login.py +++ b/webapp_login.py @@ -84,7 +84,7 @@ def htmlLogin(cssCache: {}, translate: {}, copyfile(baseDir + '/img/login.png', loginImageFilename) textModeLogo = getTextModeLogo(baseDir) - textModeLogoHtml = htmlKeyboardNavigation(textModeLogo, {}) + textModeLogoHtml = htmlKeyboardNavigation(textModeLogo, {}, {}) if os.path.isfile(baseDir + '/accounts/login-background-custom.jpg'): if not os.path.isfile(baseDir + '/accounts/login-background.jpg'): diff --git a/webapp_person_options.py b/webapp_person_options.py index dc9ccbf04..8019a87c1 100644 --- a/webapp_person_options.py +++ b/webapp_person_options.py @@ -119,7 +119,7 @@ def htmlPersonOptions(defaultTimeline: str, instanceTitle = \ getConfigParam(baseDir, 'instanceTitle') optionsStr = htmlHeaderWithExternalStyle(cssFilename, instanceTitle) - optionsStr += htmlKeyboardNavigation(textModeBanner, {}) + optionsStr += htmlKeyboardNavigation(textModeBanner, {}, {}) optionsStr += '

\n' optionsStr += '
\n' optionsStr += '
\n' diff --git a/webapp_profile.py b/webapp_profile.py index 0f252853e..5f371e0a5 100644 --- a/webapp_profile.py +++ b/webapp_profile.py @@ -755,7 +755,19 @@ def htmlProfile(rssIconAtTop: bool, menuShares: userPathStr + '/shares#timeline', menuLogout: '/logout' } - profileStr = htmlKeyboardNavigation(textModeBanner, navLinks) + navAccessKeys = { + menuTimeline: 't', + menuEdit: 'e', + menuFollowing: 'f', + menuFollowers: 'g', + menuRoles: 'o', + menuSkills: 's', + menuShares: 'h', + menuLogout: 'x' + } + profileStr = htmlKeyboardNavigation(textModeBanner, + navLinks, navAccessKeys, + navAccessKeys) profileStr += profileHeaderStr + donateSection profileStr += '
\n' @@ -1471,7 +1483,12 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str, menuProfile: userPathStr, menuTimeline: userTimalineStr } - editProfileForm += htmlKeyboardNavigation(textModeBanner, navLinks) + navAccessKeys = { + menuProfile: 'p', + menuTimeline: 't' + } + editProfileForm += htmlKeyboardNavigation(textModeBanner, + navLinks, navAccessKeys) # top banner editProfileForm += \ diff --git a/webapp_search.py b/webapp_search.py index 16f548266..048ba1647 100644 --- a/webapp_search.py +++ b/webapp_search.py @@ -342,7 +342,7 @@ def htmlSearch(cssCache: {}, translate: {}, searchBannerFile, searchBannerFilename = \ getSearchBannerFile(baseDir, searchNickname, domain, theme) - textModeBannerStr = htmlKeyboardNavigation(textModeBanner, {}) + textModeBannerStr = htmlKeyboardNavigation(textModeBanner, {}, {}) if textModeBannerStr is None: textModeBannerStr = '' diff --git a/webapp_timeline.py b/webapp_timeline.py index 129085978..0d76fed0e 100644 --- a/webapp_timeline.py +++ b/webapp_timeline.py @@ -479,10 +479,26 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, menuNewswire: usersPath + '/newswiremobile', menuLinks: usersPath + '/linksmobile' } + navAccessKeys = { + menuProfile: 'p', + menuInbox: 'i', + menuSearch: '/', + menuNewPost: 'n', + menuCalendar: 'c', + menuDM: 'm', + menuReplies: 'r', + menuOutbox: 'o', + menuBookmarks: 'k', + menuShares: 's', + menuBlogs: 'b', + menuNewswire: 'w', + menuLinks: 'l' + } if moderator: navLinks[menuModeration] = usersPath + '/moderation#modtimeline' - tlStr += htmlKeyboardNavigation(textModeBanner, navLinks, None, - usersPath, translate, followApprovals) + tlStr += htmlKeyboardNavigation(textModeBanner, navLinks, navAccessKeys, + None, usersPath, translate, + followApprovals) # banner and row of buttons tlStr += \ diff --git a/webapp_utils.py b/webapp_utils.py index c3cbcfc56..d154d8a51 100644 --- a/webapp_utils.py +++ b/webapp_utils.py @@ -1114,7 +1114,7 @@ def htmlHideFromScreenReader(htmlStr: str) -> str: return '' -def htmlKeyboardNavigation(banner: str, links: {}, +def htmlKeyboardNavigation(banner: str, links: {}, accessKeys: {}, subHeading=None, usersPath=None, translate=None, followApprovals=False) -> str: @@ -1138,8 +1138,12 @@ def htmlKeyboardNavigation(banner: str, links: {}, # show the list of links for title, url in links.items(): + accessKeyStr = '' + if accessKeys.get(title): + accessKeyStr = 'accesskey="' + accessKeys[title] + '"' + htmlStr += '
  • \n' htmlStr += '
    \n' return htmlStr From 19964ed80f138a9db8b1c705927d8129de354db2 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 22 Apr 2021 12:57:35 +0100 Subject: [PATCH 08/54] Twice argument --- webapp_profile.py | 3 +-- webapp_timeline.py | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/webapp_profile.py b/webapp_profile.py index 5f371e0a5..52916a03f 100644 --- a/webapp_profile.py +++ b/webapp_profile.py @@ -766,8 +766,7 @@ def htmlProfile(rssIconAtTop: bool, menuLogout: 'x' } profileStr = htmlKeyboardNavigation(textModeBanner, - navLinks, navAccessKeys, - navAccessKeys) + navLinks, navAccessKeys) profileStr += profileHeaderStr + donateSection profileStr += '
    \n' diff --git a/webapp_timeline.py b/webapp_timeline.py index 0d76fed0e..c5b358305 100644 --- a/webapp_timeline.py +++ b/webapp_timeline.py @@ -487,9 +487,9 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, menuCalendar: 'c', menuDM: 'm', menuReplies: 'r', - menuOutbox: 'o', + menuOutbox: 's', menuBookmarks: 'k', - menuShares: 's', + menuShares: 'h', menuBlogs: 'b', menuNewswire: 'w', menuLinks: 'l' From 4d8eb8e4d94123924b5c9a122f595b879321d9a1 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 22 Apr 2021 13:13:45 +0100 Subject: [PATCH 09/54] Key shortcuts --- webapp_timeline.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webapp_timeline.py b/webapp_timeline.py index c5b358305..f4bf1b340 100644 --- a/webapp_timeline.py +++ b/webapp_timeline.py @@ -485,9 +485,9 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, menuSearch: '/', menuNewPost: 'n', menuCalendar: 'c', - menuDM: 'm', + menuDM: 'd', menuReplies: 'r', - menuOutbox: 's', + menuOutbox: 'o', menuBookmarks: 'k', menuShares: 'h', menuBlogs: 'b', From 0bdc0c15eabf005d613f67841116a27cb799cbca Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 22 Apr 2021 13:17:20 +0100 Subject: [PATCH 10/54] Outbox --- webapp_timeline.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webapp_timeline.py b/webapp_timeline.py index f4bf1b340..76d90fc1a 100644 --- a/webapp_timeline.py +++ b/webapp_timeline.py @@ -471,7 +471,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, menuCalendar: usersPath + '/calendar', menuDM: usersPath + '/dm#timelineposts', menuReplies: usersPath + '/tlreplies#timelineposts', - menuOutbox: usersPath + '/inbox#timelineposts', + menuOutbox: usersPath + '/outbox#timelineposts', menuBookmarks: usersPath + '/tlbookmarks#timelineposts', menuShares: usersPath + '/tlshares#timelineposts', menuBlogs: usersPath + '/tlblogs#timelineposts', @@ -487,7 +487,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, menuCalendar: 'c', menuDM: 'd', menuReplies: 'r', - menuOutbox: 'o', + menuOutbox: 's', menuBookmarks: 'k', menuShares: 'h', menuBlogs: 'b', From 597ae365dc21e3408e10ad2ecbc0ba1febe630ae Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 22 Apr 2021 13:31:20 +0100 Subject: [PATCH 11/54] Moderation access key --- webapp_timeline.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webapp_timeline.py b/webapp_timeline.py index 76d90fc1a..a8687fd9c 100644 --- a/webapp_timeline.py +++ b/webapp_timeline.py @@ -475,7 +475,6 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, menuBookmarks: usersPath + '/tlbookmarks#timelineposts', menuShares: usersPath + '/tlshares#timelineposts', menuBlogs: usersPath + '/tlblogs#timelineposts', - # menuEvents: usersPath + '/tlevents#timelineposts', menuNewswire: usersPath + '/newswiremobile', menuLinks: usersPath + '/linksmobile' } @@ -492,7 +491,8 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, menuShares: 'h', menuBlogs: 'b', menuNewswire: 'w', - menuLinks: 'l' + menuLinks: 'l', + menuModeration: 'm' } if moderator: navLinks[menuModeration] = usersPath + '/moderation#modtimeline' From 6254c30c632c9fb63bbd82c12ac13395c484bb59 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 22 Apr 2021 13:45:31 +0100 Subject: [PATCH 12/54] Setting keyboard shortcuts for timeline --- daemon.py | 39 +++++++++++----- webapp_moderation.py | 5 ++- webapp_timeline.py | 104 ++++++++++++++++++++++++++----------------- 3 files changed, 94 insertions(+), 54 deletions(-) diff --git a/daemon.py b/daemon.py index 967f55b9f..b400099c3 100644 --- a/daemon.py +++ b/daemon.py @@ -7852,7 +7852,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.themeName, self.server.peertubeInstances, self.server.allowLocalNetworkAccess, - self.server.textModeBanner) + self.server.textModeBanner, + self.server.accessKeys) if GETstartTime: self._benchmarkGETtimings(GETstartTime, GETtimings, 'show status done', @@ -7981,7 +7982,8 @@ class PubServer(BaseHTTPRequestHandler): authorized, self.server.themeName, self.server.peertubeInstances, self.server.allowLocalNetworkAccess, - self.server.textModeBanner) + self.server.textModeBanner, + self.server.accessKeys) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8103,7 +8105,8 @@ class PubServer(BaseHTTPRequestHandler): authorized, self.server.themeName, self.server.peertubeInstances, self.server.allowLocalNetworkAccess, - self.server.textModeBanner) + self.server.textModeBanner, + self.server.accessKeys) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8226,7 +8229,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.themeName, self.server.peertubeInstances, self.server.allowLocalNetworkAccess, - self.server.textModeBanner) + self.server.textModeBanner, + self.server.accessKeys) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8349,7 +8353,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.themeName, self.server.peertubeInstances, self.server.allowLocalNetworkAccess, - self.server.textModeBanner) + self.server.textModeBanner, + self.server.accessKeys) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8481,7 +8486,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.themeName, self.server.peertubeInstances, self.server.allowLocalNetworkAccess, - self.server.textModeBanner) + self.server.textModeBanner, + self.server.accessKeys) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8609,7 +8615,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.themeName, self.server.peertubeInstances, self.server.allowLocalNetworkAccess, - self.server.textModeBanner) + self.server.textModeBanner, + self.server.accessKeys) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8698,7 +8705,8 @@ class PubServer(BaseHTTPRequestHandler): authorized, self.server.themeName, self.server.peertubeInstances, self.server.allowLocalNetworkAccess, - self.server.textModeBanner) + self.server.textModeBanner, + self.server.accessKeys) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8804,7 +8812,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.themeName, self.server.peertubeInstances, self.server.allowLocalNetworkAccess, - self.server.textModeBanner) + self.server.textModeBanner, + self.server.accessKeys) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8930,7 +8939,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.themeName, self.server.peertubeInstances, self.server.allowLocalNetworkAccess, - self.server.textModeBanner) + self.server.textModeBanner, + self.server.accessKeys) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -9048,7 +9058,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.themeName, self.server.peertubeInstances, self.server.allowLocalNetworkAccess, - self.server.textModeBanner) + self.server.textModeBanner, + self.server.accessKeys) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -9156,7 +9167,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.themeName, self.server.peertubeInstances, self.server.allowLocalNetworkAccess, - self.server.textModeBanner) + self.server.textModeBanner, + self.server.accessKeys) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -14477,6 +14489,9 @@ def runDaemon(brochMode: bool, # ASCII/ANSI text banner used in shell browsers, such as Lynx httpd.textModeBanner = getTextModeBanner(baseDir) + # key shortcuts SHIFT + ALT + [key] + httpd.accessKeys = {} + httpd.unitTest = unitTest httpd.allowLocalNetworkAccess = allowLocalNetworkAccess if unitTest: diff --git a/webapp_moderation.py b/webapp_moderation.py index a8e90fdb9..07d64bbdd 100644 --- a/webapp_moderation.py +++ b/webapp_moderation.py @@ -44,7 +44,8 @@ def htmlModeration(cssCache: {}, defaultTimeline: str, authorized: bool, moderationActionStr: str, theme: str, peertubeInstances: [], allowLocalNetworkAccess: bool, - textModeBanner: str) -> str: + textModeBanner: str, + accessKeys: {}) -> str: """Show the moderation feed as html This is what you see when selecting the "mod" timeline """ @@ -60,7 +61,7 @@ def htmlModeration(cssCache: {}, defaultTimeline: str, iconsAsButtons, rssIconAtTop, publishButtonAtTop, authorized, moderationActionStr, theme, peertubeInstances, allowLocalNetworkAccess, - textModeBanner) + textModeBanner, accessKeys) def htmlAccountInfo(cssCache: {}, translate: {}, diff --git a/webapp_timeline.py b/webapp_timeline.py index a8687fd9c..84a1cd059 100644 --- a/webapp_timeline.py +++ b/webapp_timeline.py @@ -116,7 +116,8 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, theme: str, peertubeInstances: [], allowLocalNetworkAccess: bool, - textModeBanner: str) -> str: + textModeBanner: str, + accessKeys: {}) -> str: """Show the timeline as html """ enableTimingLog = False @@ -478,25 +479,26 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, menuNewswire: usersPath + '/newswiremobile', menuLinks: usersPath + '/linksmobile' } - navAccessKeys = { - menuProfile: 'p', - menuInbox: 'i', - menuSearch: '/', - menuNewPost: 'n', - menuCalendar: 'c', - menuDM: 'd', - menuReplies: 'r', - menuOutbox: 's', - menuBookmarks: 'k', - menuShares: 'h', - menuBlogs: 'b', - menuNewswire: 'w', - menuLinks: 'l', - menuModeration: 'm' - } + if not accessKeys: + accessKeys = { + menuProfile: 'p', + menuInbox: 'i', + menuSearch: '/', + menuNewPost: 'n', + menuCalendar: 'c', + menuDM: 'd', + menuReplies: 'r', + menuOutbox: 's', + menuBookmarks: 'k', + menuShares: 'h', + menuBlogs: 'b', + menuNewswire: 'w', + menuLinks: 'l', + menuModeration: 'm' + } if moderator: navLinks[menuModeration] = usersPath + '/moderation#modtimeline' - tlStr += htmlKeyboardNavigation(textModeBanner, navLinks, navAccessKeys, + tlStr += htmlKeyboardNavigation(textModeBanner, navLinks, accessKeys, None, usersPath, translate, followApprovals) @@ -910,7 +912,8 @@ def htmlShares(cssCache: {}, defaultTimeline: str, authorized: bool, theme: str, peertubeInstances: [], allowLocalNetworkAccess: bool, - textModeBanner: str) -> str: + textModeBanner: str, + accessKeys: {}) -> str: """Show the shares timeline as html """ manuallyApproveFollowers = \ @@ -931,7 +934,8 @@ def htmlShares(cssCache: {}, defaultTimeline: str, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, authorized, None, theme, peertubeInstances, - allowLocalNetworkAccess, textModeBanner) + allowLocalNetworkAccess, textModeBanner, + accessKeys) def htmlInbox(cssCache: {}, defaultTimeline: str, @@ -953,7 +957,8 @@ def htmlInbox(cssCache: {}, defaultTimeline: str, authorized: bool, theme: str, peertubeInstances: [], allowLocalNetworkAccess: bool, - textModeBanner: str) -> str: + textModeBanner: str, + accessKeys: {}) -> str: """Show the inbox as html """ manuallyApproveFollowers = \ @@ -974,7 +979,8 @@ def htmlInbox(cssCache: {}, defaultTimeline: str, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, authorized, None, theme, peertubeInstances, - allowLocalNetworkAccess, textModeBanner) + allowLocalNetworkAccess, textModeBanner, + accessKeys) def htmlBookmarks(cssCache: {}, defaultTimeline: str, @@ -996,7 +1002,8 @@ def htmlBookmarks(cssCache: {}, defaultTimeline: str, authorized: bool, theme: str, peertubeInstances: [], allowLocalNetworkAccess: bool, - textModeBanner: str) -> str: + textModeBanner: str, + accessKeys: {}) -> str: """Show the bookmarks as html """ manuallyApproveFollowers = \ @@ -1017,7 +1024,8 @@ def htmlBookmarks(cssCache: {}, defaultTimeline: str, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, authorized, None, theme, peertubeInstances, - allowLocalNetworkAccess, textModeBanner) + allowLocalNetworkAccess, textModeBanner, + accessKeys) def htmlEvents(cssCache: {}, defaultTimeline: str, @@ -1039,7 +1047,8 @@ def htmlEvents(cssCache: {}, defaultTimeline: str, authorized: bool, theme: str, peertubeInstances: [], allowLocalNetworkAccess: bool, - textModeBanner: str) -> str: + textModeBanner: str, + accessKeys: {}) -> str: """Show the events as html """ manuallyApproveFollowers = \ @@ -1060,7 +1069,8 @@ def htmlEvents(cssCache: {}, defaultTimeline: str, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, authorized, None, theme, peertubeInstances, - allowLocalNetworkAccess, textModeBanner) + allowLocalNetworkAccess, textModeBanner, + accessKeys) def htmlInboxDMs(cssCache: {}, defaultTimeline: str, @@ -1082,7 +1092,8 @@ def htmlInboxDMs(cssCache: {}, defaultTimeline: str, authorized: bool, theme: str, peertubeInstances: [], allowLocalNetworkAccess: bool, - textModeBanner: str) -> str: + textModeBanner: str, + accessKeys: {}) -> str: """Show the DM timeline as html """ return htmlTimeline(cssCache, defaultTimeline, @@ -1098,7 +1109,8 @@ def htmlInboxDMs(cssCache: {}, defaultTimeline: str, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, authorized, None, theme, peertubeInstances, - allowLocalNetworkAccess, textModeBanner) + allowLocalNetworkAccess, textModeBanner, + accessKeys) def htmlInboxReplies(cssCache: {}, defaultTimeline: str, @@ -1120,7 +1132,8 @@ def htmlInboxReplies(cssCache: {}, defaultTimeline: str, authorized: bool, theme: str, peertubeInstances: [], allowLocalNetworkAccess: bool, - textModeBanner: str) -> str: + textModeBanner: str, + accessKeys: {}) -> str: """Show the replies timeline as html """ return htmlTimeline(cssCache, defaultTimeline, @@ -1137,7 +1150,8 @@ def htmlInboxReplies(cssCache: {}, defaultTimeline: str, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, authorized, None, theme, peertubeInstances, - allowLocalNetworkAccess, textModeBanner) + allowLocalNetworkAccess, textModeBanner, + accessKeys) def htmlInboxMedia(cssCache: {}, defaultTimeline: str, @@ -1159,7 +1173,8 @@ def htmlInboxMedia(cssCache: {}, defaultTimeline: str, authorized: bool, theme: str, peertubeInstances: [], allowLocalNetworkAccess: bool, - textModeBanner: str) -> str: + textModeBanner: str, + accessKeys: {}) -> str: """Show the media timeline as html """ return htmlTimeline(cssCache, defaultTimeline, @@ -1176,7 +1191,8 @@ def htmlInboxMedia(cssCache: {}, defaultTimeline: str, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, authorized, None, theme, peertubeInstances, - allowLocalNetworkAccess, textModeBanner) + allowLocalNetworkAccess, textModeBanner, + accessKeys) def htmlInboxBlogs(cssCache: {}, defaultTimeline: str, @@ -1198,7 +1214,8 @@ def htmlInboxBlogs(cssCache: {}, defaultTimeline: str, authorized: bool, theme: str, peertubeInstances: [], allowLocalNetworkAccess: bool, - textModeBanner: str) -> str: + textModeBanner: str, + accessKeys: {}) -> str: """Show the blogs timeline as html """ return htmlTimeline(cssCache, defaultTimeline, @@ -1215,7 +1232,8 @@ def htmlInboxBlogs(cssCache: {}, defaultTimeline: str, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, authorized, None, theme, peertubeInstances, - allowLocalNetworkAccess, textModeBanner) + allowLocalNetworkAccess, textModeBanner, + accessKeys) def htmlInboxFeatures(cssCache: {}, defaultTimeline: str, @@ -1238,7 +1256,8 @@ def htmlInboxFeatures(cssCache: {}, defaultTimeline: str, theme: str, peertubeInstances: [], allowLocalNetworkAccess: bool, - textModeBanner: str) -> str: + textModeBanner: str, + accessKeys: {}) -> str: """Show the features timeline as html """ return htmlTimeline(cssCache, defaultTimeline, @@ -1255,7 +1274,8 @@ def htmlInboxFeatures(cssCache: {}, defaultTimeline: str, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, authorized, None, theme, peertubeInstances, - allowLocalNetworkAccess, textModeBanner) + allowLocalNetworkAccess, textModeBanner, + accessKeys) def htmlInboxNews(cssCache: {}, defaultTimeline: str, @@ -1277,7 +1297,8 @@ def htmlInboxNews(cssCache: {}, defaultTimeline: str, authorized: bool, theme: str, peertubeInstances: [], allowLocalNetworkAccess: bool, - textModeBanner: str) -> str: + textModeBanner: str, + accessKeys: {}) -> str: """Show the news timeline as html """ return htmlTimeline(cssCache, defaultTimeline, @@ -1294,7 +1315,8 @@ def htmlInboxNews(cssCache: {}, defaultTimeline: str, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, authorized, None, theme, peertubeInstances, - allowLocalNetworkAccess, textModeBanner) + allowLocalNetworkAccess, textModeBanner, + accessKeys) def htmlOutbox(cssCache: {}, defaultTimeline: str, @@ -1316,7 +1338,8 @@ def htmlOutbox(cssCache: {}, defaultTimeline: str, authorized: bool, theme: str, peertubeInstances: [], allowLocalNetworkAccess: bool, - textModeBanner: str) -> str: + textModeBanner: str, + accessKeys: {}) -> str: """Show the Outbox as html """ manuallyApproveFollowers = \ @@ -1334,4 +1357,5 @@ def htmlOutbox(cssCache: {}, defaultTimeline: str, showPublishAsIcon, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, authorized, None, theme, peertubeInstances, - allowLocalNetworkAccess, textModeBanner) + allowLocalNetworkAccess, textModeBanner, + accessKeys) From 114fc7a80bbb5003f2e7b1c246ee2ad7ca2105d7 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 22 Apr 2021 13:47:19 +0100 Subject: [PATCH 13/54] Default access keys --- daemon.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/daemon.py b/daemon.py index b400099c3..d6453e1d6 100644 --- a/daemon.py +++ b/daemon.py @@ -14490,7 +14490,22 @@ def runDaemon(brochMode: bool, httpd.textModeBanner = getTextModeBanner(baseDir) # key shortcuts SHIFT + ALT + [key] - httpd.accessKeys = {} + httpd.accessKeys = { + menuProfile: 'p', + menuInbox: 'i', + menuSearch: '/', + menuNewPost: 'n', + menuCalendar: 'c', + menuDM: 'd', + menuReplies: 'r', + menuOutbox: 's', + menuBookmarks: 'k', + menuShares: 'h', + menuBlogs: 'b', + menuNewswire: 'w', + menuLinks: 'l', + menuModeration: 'm' + } httpd.unitTest = unitTest httpd.allowLocalNetworkAccess = allowLocalNetworkAccess From 822e68963277ecd58ed02ab55c0a3d7373de1cf1 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 22 Apr 2021 14:09:03 +0100 Subject: [PATCH 14/54] Simplify --- webapp_timeline.py | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/webapp_timeline.py b/webapp_timeline.py index 84a1cd059..e8c5ecff8 100644 --- a/webapp_timeline.py +++ b/webapp_timeline.py @@ -479,23 +479,6 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, menuNewswire: usersPath + '/newswiremobile', menuLinks: usersPath + '/linksmobile' } - if not accessKeys: - accessKeys = { - menuProfile: 'p', - menuInbox: 'i', - menuSearch: '/', - menuNewPost: 'n', - menuCalendar: 'c', - menuDM: 'd', - menuReplies: 'r', - menuOutbox: 's', - menuBookmarks: 'k', - menuShares: 'h', - menuBlogs: 'b', - menuNewswire: 'w', - menuLinks: 'l', - menuModeration: 'm' - } if moderator: navLinks[menuModeration] = usersPath + '/moderation#modtimeline' tlStr += htmlKeyboardNavigation(textModeBanner, navLinks, accessKeys, From 5bbe8c4afee9a58fea182319417688c3284ab762 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 22 Apr 2021 14:11:15 +0100 Subject: [PATCH 15/54] Quotes --- daemon.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/daemon.py b/daemon.py index d6453e1d6..7794aa78f 100644 --- a/daemon.py +++ b/daemon.py @@ -14491,20 +14491,20 @@ def runDaemon(brochMode: bool, # key shortcuts SHIFT + ALT + [key] httpd.accessKeys = { - menuProfile: 'p', - menuInbox: 'i', - menuSearch: '/', - menuNewPost: 'n', - menuCalendar: 'c', - menuDM: 'd', - menuReplies: 'r', - menuOutbox: 's', - menuBookmarks: 'k', - menuShares: 'h', - menuBlogs: 'b', - menuNewswire: 'w', - menuLinks: 'l', - menuModeration: 'm' + 'menuProfile': 'p', + 'menuInbox': 'i', + 'menuSearch': '/', + 'menuNewPost': 'n', + 'menuCalendar': 'c', + 'menuDM': 'd', + 'menuReplies': 'r', + 'menuOutbox': 's', + 'menuBookmarks': 'k', + 'menuShares': 'h', + 'menuBlogs': 'b', + 'menuNewswire': 'w', + 'menuLinks': 'l', + 'menuModeration': 'm' } httpd.unitTest = unitTest From 73860b1d441dad4a2b0604b137fabde30971d38a Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 22 Apr 2021 14:27:27 +0100 Subject: [PATCH 16/54] Variable names --- webapp_timeline.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/webapp_timeline.py b/webapp_timeline.py index e8c5ecff8..2298dd019 100644 --- a/webapp_timeline.py +++ b/webapp_timeline.py @@ -479,9 +479,14 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, menuNewswire: usersPath + '/newswiremobile', menuLinks: usersPath + '/linksmobile' } + navAccessKeys = {} + for variableName, key in accessKeys.items(): + if not locals().get(variableName): + continue + navAccessKeys[locals()[variableName]] = key if moderator: navLinks[menuModeration] = usersPath + '/moderation#modtimeline' - tlStr += htmlKeyboardNavigation(textModeBanner, navLinks, accessKeys, + tlStr += htmlKeyboardNavigation(textModeBanner, navLinks, navAccessKeys, None, usersPath, translate, followApprovals) From b4a26ef2ab7d8d3593396b04f8f9c3db9cca636e Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 22 Apr 2021 15:12:59 +0100 Subject: [PATCH 17/54] Access keys on profile screen --- daemon.py | 15 ++++++++++++++- webapp_profile.py | 18 +++++++----------- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/daemon.py b/daemon.py index 7794aa78f..42ac87698 100644 --- a/daemon.py +++ b/daemon.py @@ -7365,6 +7365,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.allowLocalNetworkAccess, self.server.textModeBanner, self.server.debug, + self.server.accessKeys, actorJson['roles'], None, None) msg = msg.encode('utf-8') @@ -7454,6 +7455,7 @@ class PubServer(BaseHTTPRequestHandler): allowLocalNetworkAccess, self.server.textModeBanner, self.server.debug, + self.server.accessKeys, actorJson['skills'], None, None) msg = msg.encode('utf-8') @@ -9271,6 +9273,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.allowLocalNetworkAccess, self.server.textModeBanner, self.server.debug, + self.server.accessKeys, shares, pageNumber, sharesPerPage) msg = msg.encode('utf-8') @@ -9371,6 +9374,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.allowLocalNetworkAccess, self.server.textModeBanner, self.server.debug, + self.server.accessKeys, following, pageNumber, followsPerPage).encode('utf-8') @@ -9470,6 +9474,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.allowLocalNetworkAccess, self.server.textModeBanner, self.server.debug, + self.server.accessKeys, followers, pageNumber, followsPerPage).encode('utf-8') @@ -9592,6 +9597,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.allowLocalNetworkAccess, self.server.textModeBanner, self.server.debug, + self.server.accessKeys, None, None).encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -14491,6 +14497,8 @@ def runDaemon(brochMode: bool, # key shortcuts SHIFT + ALT + [key] httpd.accessKeys = { + 'menuTimeline': 't', + 'menuEdit': 'e', 'menuProfile': 'p', 'menuInbox': 'i', 'menuSearch': '/', @@ -14504,7 +14512,12 @@ def runDaemon(brochMode: bool, 'menuBlogs': 'b', 'menuNewswire': 'w', 'menuLinks': 'l', - 'menuModeration': 'm' + 'menuModeration': 'm', + 'menuFollowing': 'f', + 'menuFollowers': 'g', + 'menuRoles': 'o', + 'menuSkills': 'a', + 'menuLogout': 'x' } httpd.unitTest = unitTest diff --git a/webapp_profile.py b/webapp_profile.py index 52916a03f..c9112ae98 100644 --- a/webapp_profile.py +++ b/webapp_profile.py @@ -489,7 +489,7 @@ def htmlProfile(rssIconAtTop: bool, peertubeInstances: [], allowLocalNetworkAccess: bool, textModeBanner: str, - debug: bool, + debug: bool, accessKeys: {}, extraJson=None, pageNumber=None, maxItemsPerPage=None) -> str: """Show the profile page as html @@ -755,16 +755,12 @@ def htmlProfile(rssIconAtTop: bool, menuShares: userPathStr + '/shares#timeline', menuLogout: '/logout' } - navAccessKeys = { - menuTimeline: 't', - menuEdit: 'e', - menuFollowing: 'f', - menuFollowers: 'g', - menuRoles: 'o', - menuSkills: 's', - menuShares: 'h', - menuLogout: 'x' - } + navAccessKeys = {} + for variableName, key in accessKeys.items(): + if not locals().get(variableName): + continue + navAccessKeys[locals()[variableName]] = key + profileStr = htmlKeyboardNavigation(textModeBanner, navLinks, navAccessKeys) From a8063e1c0dd6a433d073d108886e6801e7a6f8fe Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 22 Apr 2021 16:06:24 +0100 Subject: [PATCH 18/54] Key access to individual timeline posts --- inbox.py | 2 +- webapp_confirm.py | 2 +- webapp_frontscreen.py | 2 +- webapp_post.py | 43 ++++++++++++++++++++++++++++++++----------- webapp_profile.py | 4 ++-- webapp_search.py | 4 ++-- webapp_timeline.py | 5 +++-- 7 files changed, 42 insertions(+), 20 deletions(-) diff --git a/inbox.py b/inbox.py index da64d8f54..747f29936 100644 --- a/inbox.py +++ b/inbox.py @@ -178,7 +178,7 @@ def _inboxStorePostToHtmlCache(recentPostsCache: {}, maxRecentPosts: int, httpPrefix, __version__, boxname, None, showPublishedDateOnly, peertubeInstances, allowLocalNetworkAccess, - themeName, + themeName, 0, not isDM(postJsonObject), True, True, False, True) diff --git a/webapp_confirm.py b/webapp_confirm.py index 346d94893..7442fd6d2 100644 --- a/webapp_confirm.py +++ b/webapp_confirm.py @@ -73,7 +73,7 @@ def htmlConfirmDelete(cssCache: {}, YTReplacementDomain, showPublishedDateOnly, peertubeInstances, allowLocalNetworkAccess, - themeName, + themeName, 0, False, False, False, False, False) deletePostStr += '
    ' deletePostStr += \ diff --git a/webapp_frontscreen.py b/webapp_frontscreen.py index 0d3d18486..2f725acee 100644 --- a/webapp_frontscreen.py +++ b/webapp_frontscreen.py @@ -72,7 +72,7 @@ def _htmlFrontScreenPosts(recentPostsCache: {}, maxRecentPosts: int, showPublishedDateOnly, peertubeInstances, allowLocalNetworkAccess, - themeName, + themeName, 0, False, False, False, True, False) if postStr: profileStr += postStr + separatorStr diff --git a/webapp_post.py b/webapp_post.py index 4b6fdfba3..18ded1c34 100644 --- a/webapp_post.py +++ b/webapp_post.py @@ -119,7 +119,7 @@ def prepareHtmlPostNickname(nickname: str, postHtml: str) -> str: def preparePostFromHtmlCache(nickname: str, postHtml: str, boxName: str, - pageNumber: int) -> str: + pageNumber: int, accessKeyIndex: int) -> str: """Sets the page number on a cached html post """ # if on the bookmarks timeline then remain there @@ -134,6 +134,19 @@ def preparePostFromHtmlCache(nickname: str, postHtml: str, boxName: str, withPageNumber = postHtml.replace(';-999;', ';' + str(pageNumber) + ';') withPageNumber = withPageNumber.replace('?page=-999', '?page=' + str(pageNumber)) + # replace the key shortcut + for keyIndex in range(10): + keyStr = 'accesskey="' + str(keyIndex) + '"' + if keyStr in withPageNumber: + if accessKeyIndex == 0 or accessKeyIndex > 9: + withPageNumber = \ + withPageNumber.replace(keyStr, '') + else: + withPageNumber = \ + withPageNumber.replace(keyStr, + 'accesskey="' + + str(accessKeyIndex) + '"') + break return prepareHtmlPostNickname(nickname, withPageNumber) @@ -179,7 +192,8 @@ def _getPostFromRecentCache(session, postStartTime, pageNumber: int, recentPostsCache: {}, - maxRecentPosts: int) -> str: + maxRecentPosts: int, + accessKeyIndex: int) -> str: """Attempts to get the html post from the recent posts cache in memory """ if boxName == 'tlmedia': @@ -217,7 +231,8 @@ def _getPostFromRecentCache(session, return None postHtml = \ - preparePostFromHtmlCache(nickname, postHtml, boxName, pageNumber) + preparePostFromHtmlCache(nickname, postHtml, boxName, + pageNumber, accessKeyIndex) updateRecentPostsCache(recentPostsCache, maxRecentPosts, postJsonObject, postHtml) _logPostTiming(enableTimingLog, postStartTime, '3') @@ -1140,7 +1155,7 @@ def individualPostAsHtml(allowDownloads: bool, showPublishedDateOnly: bool, peertubeInstances: [], allowLocalNetworkAccess: bool, - themeName: str, + themeName: str, accessKeyIndex: int, showRepeats=True, showIcons=False, manuallyApprovesFollowers=False, @@ -1199,7 +1214,8 @@ def individualPostAsHtml(allowDownloads: bool, postStartTime, pageNumber, recentPostsCache, - maxRecentPosts) + maxRecentPosts, + accessKeyIndex) if postHtml: return postHtml @@ -1652,8 +1668,13 @@ def individualPostAsHtml(allowDownloads: bool, postHtml = '' if boxName != 'tlmedia': - postHtml = '
    \n' + if accessKeyIndex > 0 and accessKeyIndex <= 9: + postHtml = '
    \n' + else: + postHtml = '
    \n' postHtml += avatarImageInPost postHtml += '
    \n' + \ ' ' + titleStr + \ @@ -1732,7 +1753,7 @@ def htmlIndividualPost(cssCache: {}, YTReplacementDomain, showPublishedDateOnly, peertubeInstances, - allowLocalNetworkAccess, themeName, + allowLocalNetworkAccess, themeName, 0, False, authorized, False, False, False) messageId = removeIdEnding(postJsonObject['id']) @@ -1760,7 +1781,7 @@ def htmlIndividualPost(cssCache: {}, showPublishedDateOnly, peertubeInstances, allowLocalNetworkAccess, - themeName, + themeName, 0, False, authorized, False, False, False) + postStr @@ -1791,7 +1812,7 @@ def htmlIndividualPost(cssCache: {}, showPublishedDateOnly, peertubeInstances, allowLocalNetworkAccess, - themeName, + themeName, 0, False, authorized, False, False, False) cssFilename = baseDir + '/epicyon-profile.css' @@ -1833,7 +1854,7 @@ def htmlPostReplies(cssCache: {}, showPublishedDateOnly, peertubeInstances, allowLocalNetworkAccess, - themeName, + themeName, 0, False, False, False, False, False) cssFilename = baseDir + '/epicyon-profile.css' diff --git a/webapp_profile.py b/webapp_profile.py index c9112ae98..9203445b1 100644 --- a/webapp_profile.py +++ b/webapp_profile.py @@ -309,7 +309,7 @@ def htmlProfileAfterSearch(cssCache: {}, YTReplacementDomain, showPublishedDateOnly, peertubeInstances, allowLocalNetworkAccess, - themeName, + themeName, 0, False, False, False, False, False) i += 1 if i >= 20: @@ -916,7 +916,7 @@ def _htmlProfilePosts(recentPostsCache: {}, maxRecentPosts: int, showPublishedDateOnly, peertubeInstances, allowLocalNetworkAccess, - themeName, + themeName, 0, False, False, False, True, False) if postStr: profileStr += postStr + separatorStr diff --git a/webapp_search.py b/webapp_search.py index 048ba1647..ec81d78cf 100644 --- a/webapp_search.py +++ b/webapp_search.py @@ -609,7 +609,7 @@ def htmlHistorySearch(cssCache: {}, translate: {}, baseDir: str, showPublishedDateOnly, peertubeInstances, allowLocalNetworkAccess, - themeName, + themeName, 0, showIndividualPostIcons, showIndividualPostIcons, False, False, False) @@ -782,7 +782,7 @@ def htmlHashtagSearch(cssCache: {}, showPublishedDateOnly, peertubeInstances, allowLocalNetworkAccess, - themeName, + themeName, 0, showRepeats, showIcons, manuallyApprovesFollowers, showPublicOnly, diff --git a/webapp_timeline.py b/webapp_timeline.py index 2298dd019..925ae1da3 100644 --- a/webapp_timeline.py +++ b/webapp_timeline.py @@ -697,7 +697,8 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, preparePostFromHtmlCache(nickname, currTlStr, boxName, - pageNumber) + pageNumber, + itemCtr) _logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '10') @@ -726,7 +727,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, showPublishedDateOnly, peertubeInstances, allowLocalNetworkAccess, - theme, + theme, itemCtr + 1, boxName != 'dm', showIndividualPostIcons, manuallyApproveFollowers, From 7ca1a5aee9cb9ad450721cb9f4efe72c7eb7e3f6 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 22 Apr 2021 17:06:32 +0100 Subject: [PATCH 19/54] Simplify --- webapp_post.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/webapp_post.py b/webapp_post.py index 18ded1c34..9cc8617a2 100644 --- a/webapp_post.py +++ b/webapp_post.py @@ -138,14 +138,10 @@ def preparePostFromHtmlCache(nickname: str, postHtml: str, boxName: str, for keyIndex in range(10): keyStr = 'accesskey="' + str(keyIndex) + '"' if keyStr in withPageNumber: - if accessKeyIndex == 0 or accessKeyIndex > 9: - withPageNumber = \ - withPageNumber.replace(keyStr, '') - else: - withPageNumber = \ - withPageNumber.replace(keyStr, - 'accesskey="' + - str(accessKeyIndex) + '"') + withPageNumber = \ + withPageNumber.replace(keyStr, + 'accesskey="' + + str(accessKeyIndex) + '"') break return prepareHtmlPostNickname(nickname, withPageNumber) From af2baff093465e7fda6a63a58d60adb1020af443 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 22 Apr 2021 18:04:51 +0100 Subject: [PATCH 20/54] Revert "Simplify" This reverts commit 7ca1a5aee9cb9ad450721cb9f4efe72c7eb7e3f6. --- webapp_post.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/webapp_post.py b/webapp_post.py index 9cc8617a2..18ded1c34 100644 --- a/webapp_post.py +++ b/webapp_post.py @@ -138,10 +138,14 @@ def preparePostFromHtmlCache(nickname: str, postHtml: str, boxName: str, for keyIndex in range(10): keyStr = 'accesskey="' + str(keyIndex) + '"' if keyStr in withPageNumber: - withPageNumber = \ - withPageNumber.replace(keyStr, - 'accesskey="' + - str(accessKeyIndex) + '"') + if accessKeyIndex == 0 or accessKeyIndex > 9: + withPageNumber = \ + withPageNumber.replace(keyStr, '') + else: + withPageNumber = \ + withPageNumber.replace(keyStr, + 'accesskey="' + + str(accessKeyIndex) + '"') break return prepareHtmlPostNickname(nickname, withPageNumber) From e91cc35fd9adf9e9861bce3527f76b8912d8a42e Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 22 Apr 2021 18:05:10 +0100 Subject: [PATCH 21/54] Revert "Key access to individual timeline posts" This reverts commit a8063e1c0dd6a433d073d108886e6801e7a6f8fe. --- inbox.py | 2 +- webapp_confirm.py | 2 +- webapp_frontscreen.py | 2 +- webapp_post.py | 43 +++++++++++-------------------------------- webapp_profile.py | 4 ++-- webapp_search.py | 4 ++-- webapp_timeline.py | 5 ++--- 7 files changed, 20 insertions(+), 42 deletions(-) diff --git a/inbox.py b/inbox.py index 747f29936..da64d8f54 100644 --- a/inbox.py +++ b/inbox.py @@ -178,7 +178,7 @@ def _inboxStorePostToHtmlCache(recentPostsCache: {}, maxRecentPosts: int, httpPrefix, __version__, boxname, None, showPublishedDateOnly, peertubeInstances, allowLocalNetworkAccess, - themeName, 0, + themeName, not isDM(postJsonObject), True, True, False, True) diff --git a/webapp_confirm.py b/webapp_confirm.py index 7442fd6d2..346d94893 100644 --- a/webapp_confirm.py +++ b/webapp_confirm.py @@ -73,7 +73,7 @@ def htmlConfirmDelete(cssCache: {}, YTReplacementDomain, showPublishedDateOnly, peertubeInstances, allowLocalNetworkAccess, - themeName, 0, + themeName, False, False, False, False, False) deletePostStr += '
    ' deletePostStr += \ diff --git a/webapp_frontscreen.py b/webapp_frontscreen.py index 2f725acee..0d3d18486 100644 --- a/webapp_frontscreen.py +++ b/webapp_frontscreen.py @@ -72,7 +72,7 @@ def _htmlFrontScreenPosts(recentPostsCache: {}, maxRecentPosts: int, showPublishedDateOnly, peertubeInstances, allowLocalNetworkAccess, - themeName, 0, + themeName, False, False, False, True, False) if postStr: profileStr += postStr + separatorStr diff --git a/webapp_post.py b/webapp_post.py index 18ded1c34..4b6fdfba3 100644 --- a/webapp_post.py +++ b/webapp_post.py @@ -119,7 +119,7 @@ def prepareHtmlPostNickname(nickname: str, postHtml: str) -> str: def preparePostFromHtmlCache(nickname: str, postHtml: str, boxName: str, - pageNumber: int, accessKeyIndex: int) -> str: + pageNumber: int) -> str: """Sets the page number on a cached html post """ # if on the bookmarks timeline then remain there @@ -134,19 +134,6 @@ def preparePostFromHtmlCache(nickname: str, postHtml: str, boxName: str, withPageNumber = postHtml.replace(';-999;', ';' + str(pageNumber) + ';') withPageNumber = withPageNumber.replace('?page=-999', '?page=' + str(pageNumber)) - # replace the key shortcut - for keyIndex in range(10): - keyStr = 'accesskey="' + str(keyIndex) + '"' - if keyStr in withPageNumber: - if accessKeyIndex == 0 or accessKeyIndex > 9: - withPageNumber = \ - withPageNumber.replace(keyStr, '') - else: - withPageNumber = \ - withPageNumber.replace(keyStr, - 'accesskey="' + - str(accessKeyIndex) + '"') - break return prepareHtmlPostNickname(nickname, withPageNumber) @@ -192,8 +179,7 @@ def _getPostFromRecentCache(session, postStartTime, pageNumber: int, recentPostsCache: {}, - maxRecentPosts: int, - accessKeyIndex: int) -> str: + maxRecentPosts: int) -> str: """Attempts to get the html post from the recent posts cache in memory """ if boxName == 'tlmedia': @@ -231,8 +217,7 @@ def _getPostFromRecentCache(session, return None postHtml = \ - preparePostFromHtmlCache(nickname, postHtml, boxName, - pageNumber, accessKeyIndex) + preparePostFromHtmlCache(nickname, postHtml, boxName, pageNumber) updateRecentPostsCache(recentPostsCache, maxRecentPosts, postJsonObject, postHtml) _logPostTiming(enableTimingLog, postStartTime, '3') @@ -1155,7 +1140,7 @@ def individualPostAsHtml(allowDownloads: bool, showPublishedDateOnly: bool, peertubeInstances: [], allowLocalNetworkAccess: bool, - themeName: str, accessKeyIndex: int, + themeName: str, showRepeats=True, showIcons=False, manuallyApprovesFollowers=False, @@ -1214,8 +1199,7 @@ def individualPostAsHtml(allowDownloads: bool, postStartTime, pageNumber, recentPostsCache, - maxRecentPosts, - accessKeyIndex) + maxRecentPosts) if postHtml: return postHtml @@ -1668,13 +1652,8 @@ def individualPostAsHtml(allowDownloads: bool, postHtml = '' if boxName != 'tlmedia': - if accessKeyIndex > 0 and accessKeyIndex <= 9: - postHtml = '
    \n' - else: - postHtml = '
    \n' + postHtml = '
    \n' postHtml += avatarImageInPost postHtml += '
    \n' + \ ' ' + titleStr + \ @@ -1753,7 +1732,7 @@ def htmlIndividualPost(cssCache: {}, YTReplacementDomain, showPublishedDateOnly, peertubeInstances, - allowLocalNetworkAccess, themeName, 0, + allowLocalNetworkAccess, themeName, False, authorized, False, False, False) messageId = removeIdEnding(postJsonObject['id']) @@ -1781,7 +1760,7 @@ def htmlIndividualPost(cssCache: {}, showPublishedDateOnly, peertubeInstances, allowLocalNetworkAccess, - themeName, 0, + themeName, False, authorized, False, False, False) + postStr @@ -1812,7 +1791,7 @@ def htmlIndividualPost(cssCache: {}, showPublishedDateOnly, peertubeInstances, allowLocalNetworkAccess, - themeName, 0, + themeName, False, authorized, False, False, False) cssFilename = baseDir + '/epicyon-profile.css' @@ -1854,7 +1833,7 @@ def htmlPostReplies(cssCache: {}, showPublishedDateOnly, peertubeInstances, allowLocalNetworkAccess, - themeName, 0, + themeName, False, False, False, False, False) cssFilename = baseDir + '/epicyon-profile.css' diff --git a/webapp_profile.py b/webapp_profile.py index 9203445b1..c9112ae98 100644 --- a/webapp_profile.py +++ b/webapp_profile.py @@ -309,7 +309,7 @@ def htmlProfileAfterSearch(cssCache: {}, YTReplacementDomain, showPublishedDateOnly, peertubeInstances, allowLocalNetworkAccess, - themeName, 0, + themeName, False, False, False, False, False) i += 1 if i >= 20: @@ -916,7 +916,7 @@ def _htmlProfilePosts(recentPostsCache: {}, maxRecentPosts: int, showPublishedDateOnly, peertubeInstances, allowLocalNetworkAccess, - themeName, 0, + themeName, False, False, False, True, False) if postStr: profileStr += postStr + separatorStr diff --git a/webapp_search.py b/webapp_search.py index ec81d78cf..048ba1647 100644 --- a/webapp_search.py +++ b/webapp_search.py @@ -609,7 +609,7 @@ def htmlHistorySearch(cssCache: {}, translate: {}, baseDir: str, showPublishedDateOnly, peertubeInstances, allowLocalNetworkAccess, - themeName, 0, + themeName, showIndividualPostIcons, showIndividualPostIcons, False, False, False) @@ -782,7 +782,7 @@ def htmlHashtagSearch(cssCache: {}, showPublishedDateOnly, peertubeInstances, allowLocalNetworkAccess, - themeName, 0, + themeName, showRepeats, showIcons, manuallyApprovesFollowers, showPublicOnly, diff --git a/webapp_timeline.py b/webapp_timeline.py index 925ae1da3..2298dd019 100644 --- a/webapp_timeline.py +++ b/webapp_timeline.py @@ -697,8 +697,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, preparePostFromHtmlCache(nickname, currTlStr, boxName, - pageNumber, - itemCtr) + pageNumber) _logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '10') @@ -727,7 +726,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, showPublishedDateOnly, peertubeInstances, allowLocalNetworkAccess, - theme, itemCtr + 1, + theme, boxName != 'dm', showIndividualPostIcons, manuallyApproveFollowers, From ae44a8814468a2805b1f1b942513520d7d9f93d7 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 22 Apr 2021 22:46:02 +0100 Subject: [PATCH 22/54] Key shortcuts screen --- daemon.py | 192 ++++++++++++++++++++++++++++++++++++++----- translations/ar.json | 25 +++++- translations/ca.json | 25 +++++- translations/cy.json | 25 +++++- translations/de.json | 25 +++++- translations/en.json | 25 +++++- translations/es.json | 25 +++++- translations/fr.json | 25 +++++- translations/ga.json | 25 +++++- translations/hi.json | 25 +++++- translations/it.json | 25 +++++- translations/ja.json | 25 +++++- translations/ku.json | 25 +++++- translations/oc.json | 25 +++++- translations/pt.json | 25 +++++- translations/ru.json | 25 +++++- translations/zh.json | 25 +++++- webapp_accesskeys.py | 95 +++++++++++++++++++++ 18 files changed, 651 insertions(+), 36 deletions(-) create mode 100644 webapp_accesskeys.py diff --git a/daemon.py b/daemon.py index 42ac87698..b6c63bf77 100644 --- a/daemon.py +++ b/daemon.py @@ -134,6 +134,8 @@ from webapp_utils import getBlogAddress from webapp_calendar import htmlCalendarDeleteConfirm from webapp_calendar import htmlCalendar from webapp_about import htmlAbout +from webapp_accesskeys import htmlAccessKeys +from webapp_accesskeys import loadAccessKeysForAccounts from webapp_confirm import htmlConfirmDelete from webapp_confirm import htmlConfirmRemoveSharedItem from webapp_confirm import htmlConfirmUnblock @@ -7342,6 +7344,11 @@ class PubServer(BaseHTTPRequestHandler): self.server.YTReplacementDomain iconsAsButtons = \ self.server.iconsAsButtons + + accessKeys = self.server.accessKeys + if self.server.keyShortcuts.get(nickname): + accessKeys = self.server.keyShortcuts[nickname] + msg = \ htmlProfile(self.server.rssIconAtTop, self.server.cssCache, @@ -7365,7 +7372,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.allowLocalNetworkAccess, self.server.textModeBanner, self.server.debug, - self.server.accessKeys, + accessKeys, actorJson['roles'], None, None) msg = msg.encode('utf-8') @@ -7432,6 +7439,10 @@ class PubServer(BaseHTTPRequestHandler): self.server.iconsAsButtons allowLocalNetworkAccess = \ self.server.allowLocalNetworkAccess + accessKeys = self.server.accessKeys + if self.server.keyShortcuts.get(nickname): + accessKeys = \ + self.server.keyShortcuts[nickname] msg = \ htmlProfile(self.server.rssIconAtTop, self.server.cssCache, @@ -7455,7 +7466,7 @@ class PubServer(BaseHTTPRequestHandler): allowLocalNetworkAccess, self.server.textModeBanner, self.server.debug, - self.server.accessKeys, + accessKeys, actorJson['skills'], None, None) msg = msg.encode('utf-8') @@ -7823,6 +7834,12 @@ class PubServer(BaseHTTPRequestHandler): fullWidthTimelineButtonHeader = \ self.server.fullWidthTimelineButtonHeader minimalNick = self._isMinimal(nickname) + + accessKeys = self.server.accessKeys + if self.server.keyShortcuts.get(nickname): + accessKeys = \ + self.server.keyShortcuts[nickname] + msg = htmlInbox(self.server.cssCache, defaultTimeline, recentPostsCache, @@ -7855,7 +7872,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.peertubeInstances, self.server.allowLocalNetworkAccess, self.server.textModeBanner, - self.server.accessKeys) + accessKeys) if GETstartTime: self._benchmarkGETtimings(GETstartTime, GETtimings, 'show status done', @@ -7953,6 +7970,12 @@ class PubServer(BaseHTTPRequestHandler): fullWidthTimelineButtonHeader = \ self.server.fullWidthTimelineButtonHeader minimalNick = self._isMinimal(nickname) + + accessKeys = self.server.accessKeys + if self.server.keyShortcuts.get(nickname): + accessKeys = \ + self.server.keyShortcuts[nickname] + msg = \ htmlInboxDMs(self.server.cssCache, self.server.defaultTimeline, @@ -7985,7 +8008,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.peertubeInstances, self.server.allowLocalNetworkAccess, self.server.textModeBanner, - self.server.accessKeys) + accessKeys) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8076,6 +8099,12 @@ class PubServer(BaseHTTPRequestHandler): fullWidthTimelineButtonHeader = \ self.server.fullWidthTimelineButtonHeader minimalNick = self._isMinimal(nickname) + + accessKeys = self.server.accessKeys + if self.server.keyShortcuts.get(nickname): + accessKeys = \ + self.server.keyShortcuts[nickname] + msg = \ htmlInboxReplies(self.server.cssCache, self.server.defaultTimeline, @@ -8108,7 +8137,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.peertubeInstances, self.server.allowLocalNetworkAccess, self.server.textModeBanner, - self.server.accessKeys) + accessKeys) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8199,6 +8228,12 @@ class PubServer(BaseHTTPRequestHandler): fullWidthTimelineButtonHeader = \ self.server.fullWidthTimelineButtonHeader minimalNick = self._isMinimal(nickname) + + accessKeys = self.server.accessKeys + if self.server.keyShortcuts.get(nickname): + accessKeys = \ + self.server.keyShortcuts[nickname] + msg = \ htmlInboxMedia(self.server.cssCache, self.server.defaultTimeline, @@ -8232,7 +8267,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.peertubeInstances, self.server.allowLocalNetworkAccess, self.server.textModeBanner, - self.server.accessKeys) + accessKeys) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8323,6 +8358,12 @@ class PubServer(BaseHTTPRequestHandler): fullWidthTimelineButtonHeader = \ self.server.fullWidthTimelineButtonHeader minimalNick = self._isMinimal(nickname) + + accessKeys = self.server.accessKeys + if self.server.keyShortcuts.get(nickname): + accessKeys = \ + self.server.keyShortcuts[nickname] + msg = \ htmlInboxBlogs(self.server.cssCache, self.server.defaultTimeline, @@ -8356,7 +8397,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.peertubeInstances, self.server.allowLocalNetworkAccess, self.server.textModeBanner, - self.server.accessKeys) + accessKeys) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8455,6 +8496,12 @@ class PubServer(BaseHTTPRequestHandler): fullWidthTimelineButtonHeader = \ self.server.fullWidthTimelineButtonHeader minimalNick = self._isMinimal(nickname) + + accessKeys = self.server.accessKeys + if self.server.keyShortcuts.get(nickname): + accessKeys = \ + self.server.keyShortcuts[nickname] + msg = \ htmlInboxNews(self.server.cssCache, self.server.defaultTimeline, @@ -8489,7 +8536,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.peertubeInstances, self.server.allowLocalNetworkAccess, self.server.textModeBanner, - self.server.accessKeys) + accessKeys) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8585,6 +8632,12 @@ class PubServer(BaseHTTPRequestHandler): fullWidthTimelineButtonHeader = \ self.server.fullWidthTimelineButtonHeader minimalNick = self._isMinimal(nickname) + + accessKeys = self.server.accessKeys + if self.server.keyShortcuts.get(nickname): + accessKeys = \ + self.server.keyShortcuts[nickname] + msg = \ htmlInboxFeatures(self.server.cssCache, self.server.defaultTimeline, @@ -8618,7 +8671,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.peertubeInstances, self.server.allowLocalNetworkAccess, self.server.textModeBanner, - self.server.accessKeys) + accessKeys) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8678,6 +8731,12 @@ class PubServer(BaseHTTPRequestHandler): pageNumber = int(pageNumber) else: pageNumber = 1 + + accessKeys = self.server.accessKeys + if self.server.keyShortcuts.get(nickname): + accessKeys = \ + self.server.keyShortcuts[nickname] + msg = \ htmlShares(self.server.cssCache, self.server.defaultTimeline, @@ -8708,7 +8767,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.peertubeInstances, self.server.allowLocalNetworkAccess, self.server.textModeBanner, - self.server.accessKeys) + accessKeys) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8782,6 +8841,12 @@ class PubServer(BaseHTTPRequestHandler): fullWidthTimelineButtonHeader = \ self.server.fullWidthTimelineButtonHeader minimalNick = self._isMinimal(nickname) + + accessKeys = self.server.accessKeys + if self.server.keyShortcuts.get(nickname): + accessKeys = \ + self.server.keyShortcuts[nickname] + msg = \ htmlBookmarks(self.server.cssCache, self.server.defaultTimeline, @@ -8815,7 +8880,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.peertubeInstances, self.server.allowLocalNetworkAccess, self.server.textModeBanner, - self.server.accessKeys) + accessKeys) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8909,6 +8974,12 @@ class PubServer(BaseHTTPRequestHandler): fullWidthTimelineButtonHeader = \ self.server.fullWidthTimelineButtonHeader minimalNick = self._isMinimal(nickname) + + accessKeys = self.server.accessKeys + if self.server.keyShortcuts.get(nickname): + accessKeys = \ + self.server.keyShortcuts[nickname] + msg = \ htmlEvents(self.server.cssCache, self.server.defaultTimeline, @@ -8942,7 +9013,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.peertubeInstances, self.server.allowLocalNetworkAccess, self.server.textModeBanner, - self.server.accessKeys) + accessKeys) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -9028,6 +9099,12 @@ class PubServer(BaseHTTPRequestHandler): fullWidthTimelineButtonHeader = \ self.server.fullWidthTimelineButtonHeader minimalNick = self._isMinimal(nickname) + + accessKeys = self.server.accessKeys + if self.server.keyShortcuts.get(nickname): + accessKeys = \ + self.server.keyShortcuts[nickname] + msg = \ htmlOutbox(self.server.cssCache, self.server.defaultTimeline, @@ -9061,7 +9138,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.peertubeInstances, self.server.allowLocalNetworkAccess, self.server.textModeBanner, - self.server.accessKeys) + accessKeys) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -9138,6 +9215,12 @@ class PubServer(BaseHTTPRequestHandler): fullWidthTimelineButtonHeader = \ self.server.fullWidthTimelineButtonHeader moderationActionStr = '' + + accessKeys = self.server.accessKeys + if self.server.keyShortcuts.get(nickname): + accessKeys = \ + self.server.keyShortcuts[nickname] + msg = \ htmlModeration(self.server.cssCache, self.server.defaultTimeline, @@ -9170,7 +9253,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.peertubeInstances, self.server.allowLocalNetworkAccess, self.server.textModeBanner, - self.server.accessKeys) + accessKeys) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -9249,6 +9332,16 @@ class PubServer(BaseHTTPRequestHandler): self._404() self.server.GETbusy = False return True + + accessKeys = self.server.accessKeys + if '/users/' in path: + nickname = path.split('/users/')[1] + if '/' in nickname: + nickname = nickname.split('/')[0] + if self.server.keyShortcuts.get(nickname): + accessKeys = \ + self.server.keyShortcuts[nickname] + msg = \ htmlProfile(self.server.rssIconAtTop, self.server.cssCache, @@ -9273,7 +9366,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.allowLocalNetworkAccess, self.server.textModeBanner, self.server.debug, - self.server.accessKeys, + accessKeys, shares, pageNumber, sharesPerPage) msg = msg.encode('utf-8') @@ -9350,6 +9443,15 @@ class PubServer(BaseHTTPRequestHandler): self.server.GETbusy = False return True + accessKeys = self.server.accessKeys + if '/users/' in path: + nickname = path.split('/users/')[1] + if '/' in nickname: + nickname = nickname.split('/')[0] + if self.server.keyShortcuts.get(nickname): + accessKeys = \ + self.server.keyShortcuts[nickname] + msg = \ htmlProfile(self.server.rssIconAtTop, self.server.cssCache, @@ -9374,7 +9476,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.allowLocalNetworkAccess, self.server.textModeBanner, self.server.debug, - self.server.accessKeys, + accessKeys, following, pageNumber, followsPerPage).encode('utf-8') @@ -9449,6 +9551,16 @@ class PubServer(BaseHTTPRequestHandler): self._404() self.server.GETbusy = False return True + + accessKeys = self.server.accessKeys + if '/users/' in path: + nickname = path.split('/users/')[1] + if '/' in nickname: + nickname = nickname.split('/')[0] + if self.server.keyShortcuts.get(nickname): + accessKeys = \ + self.server.keyShortcuts[nickname] + msg = \ htmlProfile(self.server.rssIconAtTop, self.server.cssCache, @@ -9474,7 +9586,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.allowLocalNetworkAccess, self.server.textModeBanner, self.server.debug, - self.server.accessKeys, + accessKeys, followers, pageNumber, followsPerPage).encode('utf-8') @@ -9572,6 +9684,16 @@ class PubServer(BaseHTTPRequestHandler): self._404() self.server.GETbusy = False return True + + accessKeys = self.server.accessKeys + if '/users/' in path: + nickname = path.split('/users/')[1] + if '/' in nickname: + nickname = nickname.split('/')[0] + if self.server.keyShortcuts.get(nickname): + accessKeys = \ + self.server.keyShortcuts[nickname] + msg = \ htmlProfile(self.server.rssIconAtTop, self.server.cssCache, @@ -9597,7 +9719,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.allowLocalNetworkAccess, self.server.textModeBanner, self.server.debug, - self.server.accessKeys, + accessKeys, None, None).encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -11015,6 +11137,33 @@ class PubServer(BaseHTTPRequestHandler): 'show about screen') return + if htmlGET and usersInPath and authorized and \ + self.path.endswith('/accesskeys'): + nickname = self.path.split('/users/')[1] + if '/' in nickname: + nickname = nickname.split('/')[0] + + accessKeys = self.server.accessKeys + if self.server.keyShortcuts.get(nickname): + accessKeys = \ + self.server.keyShortcuts[nickname] + + msg = \ + htmlAccessKeys(self.server.cssCache, + self.server.baseDir, + nickname, self.server.domain, + self.server.translate, + accessKeys, + self.server.accessKeys) + msg = msg.encode('utf-8') + msglen = len(msg) + self._login_headers('text/html', msglen, callingDomain) + self._write(msg) + self._benchmarkGETtimings(GETstartTime, GETtimings, + 'following accounts done', + 'show accesskeys screen') + return + self._benchmarkGETtimings(GETstartTime, GETtimings, 'following accounts done', 'show about screen done') @@ -14507,7 +14656,7 @@ def runDaemon(brochMode: bool, 'menuDM': 'd', 'menuReplies': 'r', 'menuOutbox': 's', - 'menuBookmarks': 'k', + 'menuBookmarks': 'q', 'menuShares': 'h', 'menuBlogs': 'b', 'menuNewswire': 'w', @@ -14517,8 +14666,11 @@ def runDaemon(brochMode: bool, 'menuFollowers': 'g', 'menuRoles': 'o', 'menuSkills': 'a', - 'menuLogout': 'x' + 'menuLogout': 'x', + 'menuKeys': 'k' } + httpd.keyShortcuts = {} + loadAccessKeysForAccounts(baseDir, httpd.keyShortcuts) httpd.unitTest = unitTest httpd.allowLocalNetworkAccess = allowLocalNetworkAccess diff --git a/translations/ar.json b/translations/ar.json index 1d924ac55..527b0608f 100644 --- a/translations/ar.json +++ b/translations/ar.json @@ -403,5 +403,28 @@ "shocked": "صدمت", "Encrypted": "مشفر", "Direct Message permitted instances": "الرسالة المباشرة المسموح بها", - "Direct messages are always allowed from these instances.": "الرسائل المباشرة مسموح بها دائما من هذه المثيلات." + "Direct messages are always allowed from these instances.": "الرسائل المباشرة مسموح بها دائما من هذه المثيلات.", + "Key Shortcuts": "الاختصارات الرئيسية", + "menuTimeline": "عرض الجدول الزمني", + "menuEdit": "يحرر", + "menuProfile": "عرض الملف الشخصي", + "menuInbox": "صندوق الوارد", + "menuSearch": "البحث / المتتالية", + "menuNewPost": "منشور جديد", + "menuCalendar": "تقويم", + "menuDM": "رسالة مباشرة", + "menuReplies": "الردود", + "menuOutbox": "مرسل", + "menuBookmarks": "إشارات مرجعية", + "menuShares": "البنود المشتركة", + "menuBlogs": "المدونات", + "menuNewswire": "Newswire", + "menuLinks": "روابط انترنت", + "menuModeration": "الاعتدال", + "menuFollowing": "التالية", + "menuFollowers": "متابعون", + "menuRoles": "أدوار", + "menuSkills": "مهارات", + "menuLogout": "تسجيل خروج", + "menuKeys": "الاختصارات الرئيسية" } diff --git a/translations/ca.json b/translations/ca.json index 47487a6f6..619b96bb7 100644 --- a/translations/ca.json +++ b/translations/ca.json @@ -403,5 +403,28 @@ "shocked": "sorprès", "Encrypted": "Xifrat", "Direct Message permitted instances": "Instàncies permeses del missatge directe", - "Direct messages are always allowed from these instances.": "Els missatges directes sempre estan permesos d'aquests casos." + "Direct messages are always allowed from these instances.": "Els missatges directes sempre estan permesos d'aquests casos.", + "Key Shortcuts": "Dreceres clau", + "menuTimeline": "Vista de la línia de temps", + "menuEdit": "Preprarar una edició", + "menuProfile": "Vista de perfil", + "menuInbox": "Capa inferior", + "menuSearch": "Cerca / Segueix", + "menuNewPost": "Nou missatge", + "menuCalendar": "Calendari", + "menuDM": "Missatges directes", + "menuReplies": "Resum", + "menuOutbox": "Present", + "menuBookmarks": "Adreces d'interès", + "menuShares": "Articles compartits", + "menuBlogs": "Blocs", + "menuNewswire": "Newswire", + "menuLinks": "Enllaços web", + "menuModeration": "Moderació", + "menuFollowing": "Proper", + "menuFollowers": "Seguidors", + "menuRoles": "Rols", + "menuSkills": "Habilitats", + "menuLogout": "Tancar sessió", + "menuKeys": "Dreceres clau" } diff --git a/translations/cy.json b/translations/cy.json index fe5c966be..e0c3f167e 100644 --- a/translations/cy.json +++ b/translations/cy.json @@ -403,5 +403,28 @@ "shocked": "sioc", "Encrypted": "Amgryptio", "Direct Message permitted instances": "Achosion a ganiateir negeseuon uniongyrchol", - "Direct messages are always allowed from these instances.": "Caniateir negeseuon uniongyrchol bob amser o'r achosion hyn." + "Direct messages are always allowed from these instances.": "Caniateir negeseuon uniongyrchol bob amser o'r achosion hyn.", + "Key Shortcuts": "Llwybrau byr allweddol", + "menuTimeline": "View View", + "menuEdit": "Golygaf", + "menuProfile": "Gweld Proffil", + "menuInbox": "Mewnflwch", + "menuSearch": "Chwilio / Dilyn", + "menuNewPost": "Swydd newydd", + "menuCalendar": "Galendr", + "menuDM": "Negeseuon Uniongyrchol", + "menuReplies": "Atebion", + "menuOutbox": "Hanfon", + "menuBookmarks": "Nodau tudalen", + "menuShares": "Eitemau a Rennir", + "menuBlogs": "Blogiau", + "menuNewswire": "Newswire", + "menuLinks": "Cysylltiadau", + "menuModeration": "Safoniad", + "menuFollowing": "Ddilynol", + "menuFollowers": "Ddilynwyr", + "menuRoles": "Rolau", + "menuSkills": "Medrau", + "menuLogout": "Allgofnodi", + "menuKeys": "Llwybrau byr allweddol" } diff --git a/translations/de.json b/translations/de.json index 70099d937..70427d027 100644 --- a/translations/de.json +++ b/translations/de.json @@ -403,5 +403,28 @@ "shocked": "schockiert", "Encrypted": "Verschlüsselt", "Direct Message permitted instances": "Direktnachricht erlaubte Instanzen", - "Direct messages are always allowed from these instances.": "Direkte Nachrichten sind in diesen Fällen immer zulässig." + "Direct messages are always allowed from these instances.": "Direkte Nachrichten sind in diesen Fällen immer zulässig.", + "Key Shortcuts": "Schlüsselverknüpfungen", + "menuTimeline": "Timeline-Ansicht", + "menuEdit": "Bearbeiten", + "menuProfile": "Profilansicht", + "menuInbox": "Inbox", + "menuSearch": "Suche / Folgen", + "menuNewPost": "Neuer Beitrag", + "menuCalendar": "Kalender", + "menuDM": "Direkte Nachrichten", + "menuReplies": "Antworten", + "menuOutbox": "Geschickt", + "menuBookmarks": "Lesezeichen", + "menuShares": "Gemeinsame Artikel", + "menuBlogs": "Blogs", + "menuNewswire": "Newswire", + "menuLinks": "Web-Links", + "menuModeration": "Mäßigung", + "menuFollowing": "Folgen", + "menuFollowers": "Anhänger", + "menuRoles": "Rollen", + "menuSkills": "Kompetenzen", + "menuLogout": "Ausloggen", + "menuKeys": "Schlüsselverknüpfungen" } diff --git a/translations/en.json b/translations/en.json index 328038954..c9ef9a103 100644 --- a/translations/en.json +++ b/translations/en.json @@ -403,5 +403,28 @@ "shocked": "shocked", "Encrypted": "Encrypted", "Direct Message permitted instances": "Direct Message permitted instances", - "Direct messages are always allowed from these instances.": "Direct messages are always allowed from these instances." + "Direct messages are always allowed from these instances.": "Direct messages are always allowed from these instances.", + "Key Shortcuts": "Key Shortcuts", + "menuTimeline": "Timeline view", + "menuEdit": "Edit", + "menuProfile": "Profile view", + "menuInbox": "Inbox", + "menuSearch": "Search/follow", + "menuNewPost": "New post", + "menuCalendar": "Calendar", + "menuDM": "Direct Messages", + "menuReplies": "Replies", + "menuOutbox": "Sent", + "menuBookmarks": "Bookmarks", + "menuShares": "Shared items", + "menuBlogs": "Blogs", + "menuNewswire": "Newswire", + "menuLinks": "Links", + "menuModeration": "Moderation", + "menuFollowing": "Following", + "menuFollowers": "Followers", + "menuRoles": "Roles", + "menuSkills": "Skills", + "menuLogout": "Logout", + "menuKeys": "Key Shortcuts" } diff --git a/translations/es.json b/translations/es.json index c2f3a2e74..29068b653 100644 --- a/translations/es.json +++ b/translations/es.json @@ -403,5 +403,28 @@ "shocked": "conmocionada", "Encrypted": "Cifrada", "Direct Message permitted instances": "Mensaje directo permitido instancias", - "Direct messages are always allowed from these instances.": "Los mensajes directos siempre están permitidos de estas instancias." + "Direct messages are always allowed from these instances.": "Los mensajes directos siempre están permitidos de estas instancias.", + "Key Shortcuts": "Atajos clave", + "menuTimeline": "Vista de la línea de tiempo", + "menuEdit": "Editar", + "menuProfile": "Vista del perfil", + "menuInbox": "Bandeja de entrada", + "menuSearch": "Búsqueda / Seguir", + "menuNewPost": "Nueva publicación", + "menuCalendar": "Calendario", + "menuDM": "Mensajes directos", + "menuReplies": "Respuestas", + "menuOutbox": "Enviada", + "menuBookmarks": "Marcadores", + "menuShares": "Artículos compartidos", + "menuBlogs": "Blogs", + "menuNewswire": "Newswire", + "menuLinks": "Enlaces web", + "menuModeration": "Moderación", + "menuFollowing": "Siguiente", + "menuFollowers": "De seguidores", + "menuRoles": "Roles", + "menuSkills": "Habilidades", + "menuLogout": "Cerrar sesión", + "menuKeys": "Atajos clave" } diff --git a/translations/fr.json b/translations/fr.json index 68d246462..42e0c1a4b 100644 --- a/translations/fr.json +++ b/translations/fr.json @@ -403,5 +403,28 @@ "shocked": "sous le choc", "Encrypted": "Crypté", "Direct Message permitted instances": "Message direct des instances autorisées", - "Direct messages are always allowed from these instances.": "Les messages directs sont toujours autorisés dans ces instances." + "Direct messages are always allowed from these instances.": "Les messages directs sont toujours autorisés dans ces instances.", + "Key Shortcuts": "Raccourcis clés", + "menuTimeline": "Vue de la chronologie", + "menuEdit": "Éditer", + "menuProfile": "Voir", + "menuInbox": "Boîte de réception", + "menuSearch": "Rechercher / suivre", + "menuNewPost": "Nouveau poste", + "menuCalendar": "Calendrier", + "menuDM": "Messages directs", + "menuReplies": "réponses", + "menuOutbox": "Envoyée", + "menuBookmarks": "Favoris", + "menuShares": "Articles partagés", + "menuBlogs": "Blogs", + "menuNewswire": "Newswire", + "menuLinks": "Liens web", + "menuModeration": "Modération", + "menuFollowing": "Suivante", + "menuFollowers": "Suiveuses", + "menuRoles": "Les rôles", + "menuSkills": "Compétences", + "menuLogout": "Se déconnecter", + "menuKeys": "Raccourcis clés" } diff --git a/translations/ga.json b/translations/ga.json index c8c8d8911..82ddab85a 100644 --- a/translations/ga.json +++ b/translations/ga.json @@ -403,5 +403,28 @@ "shocked": "ionadh", "Encrypted": "Criptithe", "Direct Message permitted instances": "Ceadaíonn teachtaireacht dhíreach cásanna", - "Direct messages are always allowed from these instances.": "Ceadaítear teachtaireachtaí díreacha i gcónaí ó na cásanna seo." + "Direct messages are always allowed from these instances.": "Ceadaítear teachtaireachtaí díreacha i gcónaí ó na cásanna seo.", + "Key Shortcuts": "Príomh-aicearraí", + "menuTimeline": "Amlíne View", + "menuEdit": "Eagarthóireacht a dhéanamh ar", + "menuProfile": "Dearcadh próifíle", + "menuInbox": "Bosca isteach", + "menuSearch": "Cuardaigh / Lean", + "menuNewPost": "Post nua", + "menuCalendar": "Caileandar", + "menuDM": "Teachtaireachtaí díreacha", + "menuReplies": "Freagraí", + "menuOutbox": "Seoltar", + "menuBookmarks": "Leabharmharcanna", + "menuShares": "Míreanna Comhroinnte", + "menuBlogs": "Blaganna", + "menuNewswire": "Newswire", + "menuLinks": "Naisc Ghréasáin", + "menuModeration": "Modhnóireacht a dhéanamh ar", + "menuFollowing": "Lucht tacaíochta", + "menuFollowers": "Leanúna", + "menuRoles": "Róil", + "menuSkills": "Scileanna", + "menuLogout": "Logáil Amach", + "menuKeys": "Príomh-aicearraí" } diff --git a/translations/hi.json b/translations/hi.json index b36a7ad2a..853b74725 100644 --- a/translations/hi.json +++ b/translations/hi.json @@ -403,5 +403,28 @@ "shocked": "हैरान", "Encrypted": "को गोपित", "Direct Message permitted instances": "प्रत्यक्ष संदेश अनुमत उदाहरण", - "Direct messages are always allowed from these instances.": "इन उदाहरणों से प्रत्यक्ष संदेश हमेशा अनुमति देते हैं।" + "Direct messages are always allowed from these instances.": "इन उदाहरणों से प्रत्यक्ष संदेश हमेशा अनुमति देते हैं।", + "Key Shortcuts": "कुंजी शॉर्टकट", + "menuTimeline": "समयरेखा दृश्य", + "menuEdit": "संपादित करें", + "menuProfile": "प्रोफ़ाइल दृश्य", + "menuInbox": "इनबॉक्स", + "menuSearch": "खोज / अनुसरण करें", + "menuNewPost": "नई पोस्ट", + "menuCalendar": "पंचांग", + "menuDM": "सीधे संदेश", + "menuReplies": "जवाब", + "menuOutbox": "भेज दिया", + "menuBookmarks": "बुकमार्क", + "menuShares": "साझा आइटम", + "menuBlogs": "ब्लॉग", + "menuNewswire": "न्यूज़वायर", + "menuLinks": "वेब लिंक", + "menuModeration": "संयम", + "menuFollowing": "निम्नलिखित", + "menuFollowers": "समर्थक", + "menuRoles": "भूमिकाएँ", + "menuSkills": "कौशल", + "menuLogout": "लॉग आउट", + "menuKeys": "कुंजी शॉर्टकट" } diff --git a/translations/it.json b/translations/it.json index f540050d6..b7bee1906 100644 --- a/translations/it.json +++ b/translations/it.json @@ -403,5 +403,28 @@ "shocked": "scioccata", "Encrypted": "Crittografato", "Direct Message permitted instances": "Messaggio diretto istanze consentite", - "Direct messages are always allowed from these instances.": "I messaggi diretti sono sempre ammessi da questi casi." + "Direct messages are always allowed from these instances.": "I messaggi diretti sono sempre ammessi da questi casi.", + "Key Shortcuts": "Scorciatoie chiave", + "menuTimeline": "Vista della cronologia", + "menuEdit": "Modificare", + "menuProfile": "Visualizzazione del profilo", + "menuInbox": "Posta in arrivo", + "menuSearch": "Cerca / Segui", + "menuNewPost": "Nuovo post.", + "menuCalendar": "Calendario", + "menuDM": "Messaggi diretti", + "menuReplies": "Risposte", + "menuOutbox": "Inviata", + "menuBookmarks": "Segnalibri", + "menuShares": "Articoli condivisi", + "menuBlogs": "Blog", + "menuNewswire": "Newswire", + "menuLinks": "Link internet", + "menuModeration": "Moderazione", + "menuFollowing": "A seguire", + "menuFollowers": "Seguaci", + "menuRoles": "Ruoli", + "menuSkills": "Competenze", + "menuLogout": "Disconnettersi", + "menuKeys": "Scorciatoie chiave" } diff --git a/translations/ja.json b/translations/ja.json index 8b129146e..50273899d 100644 --- a/translations/ja.json +++ b/translations/ja.json @@ -403,5 +403,28 @@ "shocked": "ショックを受けた", "Encrypted": "暗号化", "Direct Message permitted instances": "直接メッセージ許可インスタンス", - "Direct messages are always allowed from these instances.": "直接メッセージは常にこれらのインスタンスから許可されています。" + "Direct messages are always allowed from these instances.": "直接メッセージは常にこれらのインスタンスから許可されています。", + "Key Shortcuts": "キーショートカット", + "menuTimeline": "タイムラインビュー", + "menuEdit": "編集する", + "menuProfile": "プロファイルビュー", + "menuInbox": "受信箱", + "menuSearch": "検索/フォロー", + "menuNewPost": "新しい投稿", + "menuCalendar": "カレンダー", + "menuDM": "ダイレクトメッセージ", + "menuReplies": "返信", + "menuOutbox": "送り返した", + "menuBookmarks": "ブックマーク", + "menuShares": "共有アイテム", + "menuBlogs": "ブログ", + "menuNewswire": "ニューワイヤー", + "menuLinks": "Webリンク", + "menuModeration": "節度", + "menuFollowing": "以下", + "menuFollowers": "フォロワー", + "menuRoles": "役割", + "menuSkills": "スキル", + "menuLogout": "ログアウト", + "menuKeys": "キーショートカット" } diff --git a/translations/ku.json b/translations/ku.json index 86f856b8f..2595c9dea 100644 --- a/translations/ku.json +++ b/translations/ku.json @@ -403,5 +403,28 @@ "shocked": "şok kirin", "Encrypted": "Encîfre kirin", "Direct Message permitted instances": "Peyama rasterast destûrê", - "Direct messages are always allowed from these instances.": "Peyamên rasterast her gav ji van deman têne destûr kirin." + "Direct messages are always allowed from these instances.": "Peyamên rasterast her gav ji van deman têne destûr kirin.", + "Key Shortcuts": "Kurteyên Key", + "menuTimeline": "Dîtina Timeline", + "menuEdit": "Weşandin", + "menuProfile": "View Profîl", + "menuInbox": "Inbott", + "menuSearch": "Lêgerîn / bişopîne", + "menuNewPost": "Peyama nû", + "menuCalendar": "Salname", + "menuDM": "Peyamên rasterast", + "menuReplies": "Bersiv", + "menuOutbox": "Şandin", + "menuBookmarks": "Emîrê", + "menuShares": "Tiştên parvekirî", + "menuBlogs": "Blogs", + "menuNewswire": "Newswire", + "menuLinks": "Girêdanên malperê", + "menuModeration": "Nermbûn", + "menuFollowing": "Pêketînî", + "menuFollowers": "Followers", + "menuRoles": "Roles", + "menuSkills": "Şarezayên", + "menuLogout": "Derkeve", + "menuKeys": "Kurteyên Key" } diff --git a/translations/oc.json b/translations/oc.json index 370cc90dc..adc35439b 100644 --- a/translations/oc.json +++ b/translations/oc.json @@ -399,5 +399,28 @@ "shocked": "shocked", "Encrypted": "Encrypted", "Direct Message permitted instances": "Direct Message permitted instances", - "Direct messages are always allowed from these instances.": "Direct messages are always allowed from these instances." + "Direct messages are always allowed from these instances.": "Direct messages are always allowed from these instances.", + "Key Shortcuts": "Key Shortcuts", + "menuTimeline": "Timeline view", + "menuEdit": "Edit", + "menuProfile": "Profile view", + "menuInbox": "Inbox", + "menuSearch": "Search/follow", + "menuNewPost": "New post", + "menuCalendar": "Calendar", + "menuDM": "Direct Messages", + "menuReplies": "Replies", + "menuOutbox": "Sent", + "menuBookmarks": "Bookmarks", + "menuShares": "Shared items", + "menuBlogs": "Blogs", + "menuNewswire": "Newswire", + "menuLinks": "Links", + "menuModeration": "Moderation", + "menuFollowing": "Following", + "menuFollowers": "Followers", + "menuRoles": "Roles", + "menuSkills": "Skills", + "menuLogout": "Logout", + "menuKeys": "Key Shortcuts" } diff --git a/translations/pt.json b/translations/pt.json index 5ed9a87c3..7e58dc8c5 100644 --- a/translations/pt.json +++ b/translations/pt.json @@ -403,5 +403,28 @@ "shocked": "chocada", "Encrypted": "Criptografada", "Direct Message permitted instances": "Mensagens diretas permitidas instâncias", - "Direct messages are always allowed from these instances.": "Mensagens diretas são sempre permitidas a partir dessas instâncias." + "Direct messages are always allowed from these instances.": "Mensagens diretas são sempre permitidas a partir dessas instâncias.", + "Key Shortcuts": "Atalhos-chave", + "menuTimeline": "Vista da linha do tempo", + "menuEdit": "Editar", + "menuProfile": "Vista de perfil", + "menuInbox": "Caixa de entrada", + "menuSearch": "Pesquisa / Siga", + "menuNewPost": "Nova postagem", + "menuCalendar": "Calendário", + "menuDM": "Mensagens diretas", + "menuReplies": "Respostas", + "menuOutbox": "Enviei", + "menuBookmarks": "Favoritas", + "menuShares": "Itens compartilhados", + "menuBlogs": "Blogs", + "menuNewswire": "Newswire", + "menuLinks": "Links da Web", + "menuModeration": "Moderação", + "menuFollowing": "Seguindo", + "menuFollowers": "Seguidoras", + "menuRoles": "Papéis", + "menuSkills": "Habilidades", + "menuLogout": "Sair", + "menuKeys": "Atalhos-chave" } diff --git a/translations/ru.json b/translations/ru.json index 924356521..6e6e4102a 100644 --- a/translations/ru.json +++ b/translations/ru.json @@ -403,5 +403,28 @@ "shocked": "потрясенный", "Encrypted": "Зашифрованный", "Direct Message permitted instances": "Прямое сообщение разрешено экземпляры", - "Direct messages are always allowed from these instances.": "Прямые сообщения всегда допускаются из этих экземпляров." + "Direct messages are always allowed from these instances.": "Прямые сообщения всегда допускаются из этих экземпляров.", + "Key Shortcuts": "Клавичные ярлыки", + "menuTimeline": "Сроки зрения", + "menuEdit": "Редактировать", + "menuProfile": "вид профиля", + "menuInbox": "Входящие", + "menuSearch": "Поиск / следующее", + "menuNewPost": "Новый пост", + "menuCalendar": "Календарь", + "menuDM": "Прямые сообщения", + "menuReplies": "Отвечает", + "menuOutbox": "Отправил", + "menuBookmarks": "Закладки", + "menuShares": "Общие предметы", + "menuBlogs": "Блоги", + "menuNewswire": "Новобранец", + "menuLinks": "веб ссылки", + "menuModeration": "На модерации", + "menuFollowing": "Следующий", + "menuFollowers": "Подписчики", + "menuRoles": "Роли", + "menuSkills": "Навыки и умения", + "menuLogout": "Выйти", + "menuKeys": "Клавичные ярлыки" } diff --git a/translations/zh.json b/translations/zh.json index 5d566eb8e..38e8ce523 100644 --- a/translations/zh.json +++ b/translations/zh.json @@ -403,5 +403,28 @@ "shocked": "震惊的", "Encrypted": "加密的", "Direct Message permitted instances": "直接留言允许实例", - "Direct messages are always allowed from these instances.": "这些实例始终允许直接消息。" + "Direct messages are always allowed from these instances.": "这些实例始终允许直接消息。", + "Key Shortcuts": "关键捷径", + "menuTimeline": "时间表视图", + "menuEdit": "编辑", + "menuProfile": "个人资料视图", + "menuInbox": "收件箱", + "menuSearch": "搜索/关注", + "menuNewPost": "最新帖子", + "menuCalendar": "日历", + "menuDM": "直接留言", + "menuReplies": "答案", + "menuOutbox": "发送", + "menuBookmarks": "书签", + "menuShares": "共享项目", + "menuBlogs": "博客", + "menuNewswire": "新闻界.", + "menuLinks": "网页链接", + "menuModeration": "适度", + "menuFollowing": "下列的", + "menuFollowers": "追随者", + "menuRoles": "角色", + "menuSkills": "技能", + "menuLogout": "登出", + "menuKeys": "关键捷径" } diff --git a/webapp_accesskeys.py b/webapp_accesskeys.py new file mode 100644 index 000000000..466e3023e --- /dev/null +++ b/webapp_accesskeys.py @@ -0,0 +1,95 @@ +__filename__ = "webapp_accesskeys.py" +__author__ = "Bob Mottram" +__license__ = "AGPL3+" +__version__ = "1.2.0" +__maintainer__ = "Bob Mottram" +__email__ = "bob@freedombone.net" +__status__ = "Production" + +import os +from utils import loadJson +from utils import getConfigParam +from webapp_utils import htmlHeaderWithExternalStyle +from webapp_utils import htmlFooter + + +def loadAccessKeysForAccounts(baseDir: str, keyShortcuts: {}) -> None: + """Loads key shortcuts for each account + """ + for subdir, dirs, files in os.walk(baseDir + '/accounts'): + for acct in dirs: + if '@' not in acct: + continue + if 'inbox@' in acct or 'news@' in acct: + continue + accountDir = os.path.join(baseDir + '/accounts', acct) + accessKeysFilename = accountDir + '/accessKeys.json' + if not os.path.isfile(accessKeysFilename): + continue + nickname = acct.split('@')[0] + accessKeys = loadJson(accessKeysFilename) + if accessKeys: + keyShortcuts[nickname] = accessKeys + break + + +def htmlAccessKeys(cssCache: {}, baseDir: str, + nickname: str, domain: str, + translate: {}, accessKeys: {}, + defaultAccessKeys: {}) -> str: + """Show and edit key shortcuts + """ + accessKeysFilename = \ + baseDir + '/accounts/' + nickname + '@' + domain + '/accessKeys.json' + if os.path.isfile(accessKeysFilename): + accessKeysFromFile = loadJson(accessKeysFilename) + if accessKeysFromFile: + accessKeys = accessKeysFromFile + + accessKeysForm = '' + cssFilename = baseDir + '/epicyon-profile.css' + if os.path.isfile(baseDir + '/epicyon.css'): + cssFilename = baseDir + '/epicyon.css' + + instanceTitle = \ + getConfigParam(baseDir, 'instanceTitle') + accessKeysForm = htmlHeaderWithExternalStyle(cssFilename, instanceTitle) + accessKeysForm += '
    \n' + + accessKeysForm += \ + '

    ' + translate['Key Shortcuts'] + '

    \n' + + accessKeysForm += '
    \n' + + accessKeysForm += \ + '
    ' + \ + '
    \n' + + accessKeysForm += ' \n' + accessKeysForm += ' \n' + accessKeysForm += ' \n' + accessKeysForm += ' \n' + accessKeysForm += ' \n' + accessKeysForm += ' \n' + + for variableName, key in defaultAccessKeys.items(): + if not translate.get(variableName): + continue + keyStr = '' + keyStr += \ + '' + if accessKeys.get(variableName): + key = accessKeys[variableName] + keyStr += \ + '' + + accessKeysForm += ' \n' + accessKeysForm += '
    ' + keyStr = '
    \n' + accessKeysForm += '
    \n' + accessKeysForm += '
    \n' + accessKeysForm += htmlFooter() + return accessKeysForm From 4dac27b0dd84f560a1a11c6032d189fb05b12f9f Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 22 Apr 2021 23:01:25 +0100 Subject: [PATCH 23/54] Key string --- webapp_accesskeys.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/webapp_accesskeys.py b/webapp_accesskeys.py index 466e3023e..f22fac467 100644 --- a/webapp_accesskeys.py +++ b/webapp_accesskeys.py @@ -85,7 +85,8 @@ def htmlAccessKeys(cssCache: {}, baseDir: str, key = accessKeys[variableName] keyStr += \ '' - keyStr = '' + keyStr += '' + accessKeysForm += keyStr accessKeysForm += ' \n' accessKeysForm += ' \n' From bb3089b69be474a1a8719528cd6e29aba7a6afe4 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 22 Apr 2021 23:14:35 +0100 Subject: [PATCH 24/54] Column widths --- epicyon-profile.css | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/epicyon-profile.css b/epicyon-profile.css index 8b2efc23a..a44782111 100644 --- a/epicyon-profile.css +++ b/epicyon-profile.css @@ -197,6 +197,17 @@ figure { height: auto; } +.accesskeys { + border: 0; + width: 100%; +} +.accesskeys-left { + width: 80%; +} +.accesskeys-right { + width: 20%; +} + .cw { font-style: var(--cw-style); font-weight: var(--cw-weight); From 04f0d096a64249fc8465133b3c96c4a2b030c978 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 22 Apr 2021 23:15:25 +0100 Subject: [PATCH 25/54] Newline --- webapp_accesskeys.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp_accesskeys.py b/webapp_accesskeys.py index f22fac467..31aec28c9 100644 --- a/webapp_accesskeys.py +++ b/webapp_accesskeys.py @@ -85,7 +85,7 @@ def htmlAccessKeys(cssCache: {}, baseDir: str, key = accessKeys[variableName] keyStr += \ '' - keyStr += '' + keyStr += '\n' accessKeysForm += keyStr accessKeysForm += ' \n' From abafddf1b75d3c4f59ab436dc500e18ec101a1c9 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 22 Apr 2021 23:19:26 +0100 Subject: [PATCH 26/54] No style --- webapp_accesskeys.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp_accesskeys.py b/webapp_accesskeys.py index 31aec28c9..d72d2a3e3 100644 --- a/webapp_accesskeys.py +++ b/webapp_accesskeys.py @@ -84,7 +84,7 @@ def htmlAccessKeys(cssCache: {}, baseDir: str, if accessKeys.get(variableName): key = accessKeys[variableName] keyStr += \ - '' + '' keyStr += '\n' accessKeysForm += keyStr From 87ac81139306f09f3043f4f4606b4f9001cb51a1 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 22 Apr 2021 23:20:47 +0100 Subject: [PATCH 27/54] Column widths --- epicyon-profile.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/epicyon-profile.css b/epicyon-profile.css index a44782111..29978a54f 100644 --- a/epicyon-profile.css +++ b/epicyon-profile.css @@ -202,10 +202,10 @@ figure { width: 100%; } .accesskeys-left { - width: 80%; + width: 90%; } .accesskeys-right { - width: 20%; + width: 10%; } .cw { From 94b19a1646b3e3ab2ff849665152a3f43c41ca2f Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 22 Apr 2021 23:28:16 +0100 Subject: [PATCH 28/54] Back button on keys screen --- daemon.py | 3 ++- webapp_accesskeys.py | 12 ++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/daemon.py b/daemon.py index b6c63bf77..7437feb4f 100644 --- a/daemon.py +++ b/daemon.py @@ -11154,7 +11154,8 @@ class PubServer(BaseHTTPRequestHandler): nickname, self.server.domain, self.server.translate, accessKeys, - self.server.accessKeys) + self.server.accessKeys, + self.server.defaultTimeline) msg = msg.encode('utf-8') msglen = len(msg) self._login_headers('text/html', msglen, callingDomain) diff --git a/webapp_accesskeys.py b/webapp_accesskeys.py index d72d2a3e3..3efd1440e 100644 --- a/webapp_accesskeys.py +++ b/webapp_accesskeys.py @@ -36,7 +36,8 @@ def loadAccessKeysForAccounts(baseDir: str, keyShortcuts: {}) -> None: def htmlAccessKeys(cssCache: {}, baseDir: str, nickname: str, domain: str, translate: {}, accessKeys: {}, - defaultAccessKeys: {}) -> str: + defaultAccessKeys: {}, + defaultTimeline: str) -> str: """Show and edit key shortcuts """ accessKeysFilename = \ @@ -63,9 +64,12 @@ def htmlAccessKeys(cssCache: {}, baseDir: str, '/users/' + nickname + '/changeAccessKeys">\n' accessKeysForm += \ - '
    ' + \ - '
    \n' + '
    \n' + \ + ' ' + \ + '\n' + \ + ' \n
    \n' accessKeysForm += ' \n' accessKeysForm += ' \n' From 3691e1d50a6ca0662303d28858e08ba7747e9d36 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Thu, 22 Apr 2021 23:37:52 +0100 Subject: [PATCH 29/54] Back button --- webapp_accesskeys.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/webapp_accesskeys.py b/webapp_accesskeys.py index 3efd1440e..647cfbeb8 100644 --- a/webapp_accesskeys.py +++ b/webapp_accesskeys.py @@ -65,9 +65,9 @@ def htmlAccessKeys(cssCache: {}, baseDir: str, accessKeysForm += \ '
    \n' + \ - ' ' + \ - '\n' + \ + ' \n' + \ ' \n
    \n' From 5d267d32d0aeb6037e44801be354aa5f013e1c56 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 23 Apr 2021 10:15:53 +0100 Subject: [PATCH 30/54] Key shortcuts on search screen --- daemon.py | 13 ++++++++++++- translations/ar.json | 3 ++- translations/ca.json | 3 ++- translations/cy.json | 3 ++- translations/de.json | 3 ++- translations/en.json | 3 ++- translations/es.json | 3 ++- translations/fr.json | 3 ++- translations/ga.json | 3 ++- translations/hi.json | 3 ++- translations/it.json | 3 ++- translations/ja.json | 3 ++- translations/ku.json | 3 ++- translations/oc.json | 3 ++- translations/pt.json | 3 ++- translations/ru.json | 3 ++- translations/zh.json | 3 ++- webapp_accesskeys.py | 7 +++++-- webapp_search.py | 10 +++++++--- 19 files changed, 56 insertions(+), 22 deletions(-) diff --git a/daemon.py b/daemon.py index 7437feb4f..193ea3a8f 100644 --- a/daemon.py +++ b/daemon.py @@ -11758,6 +11758,15 @@ class PubServer(BaseHTTPRequestHandler): '/search?' in self.path: if '?' in self.path: self.path = self.path.split('?')[0] + + nickname = self.path.split('/users/')[1] + if '/' in nickname: + nickname = nickname.split('/')[0] + + accessKeys = self.server.accessKeys + if self.server.keyShortcuts.get(nickname): + accessKeys = self.server.keyShortcuts[nickname] + # show the search screen msg = htmlSearch(self.server.cssCache, self.server.translate, @@ -11765,7 +11774,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.domain, self.server.defaultTimeline, self.server.themeName, - self.server.textModeBanner).encode('utf-8') + self.server.textModeBanner, + accessKeys).encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, cookie, callingDomain) self._write(msg) @@ -14647,6 +14657,7 @@ def runDaemon(brochMode: bool, # key shortcuts SHIFT + ALT + [key] httpd.accessKeys = { + 'submitButton': 'y', 'menuTimeline': 't', 'menuEdit': 'e', 'menuProfile': 'p', diff --git a/translations/ar.json b/translations/ar.json index 527b0608f..5eb4c3dff 100644 --- a/translations/ar.json +++ b/translations/ar.json @@ -426,5 +426,6 @@ "menuRoles": "أدوار", "menuSkills": "مهارات", "menuLogout": "تسجيل خروج", - "menuKeys": "الاختصارات الرئيسية" + "menuKeys": "الاختصارات الرئيسية", + "submitButton": "زر الإرسال" } diff --git a/translations/ca.json b/translations/ca.json index 619b96bb7..86658f70c 100644 --- a/translations/ca.json +++ b/translations/ca.json @@ -426,5 +426,6 @@ "menuRoles": "Rols", "menuSkills": "Habilitats", "menuLogout": "Tancar sessió", - "menuKeys": "Dreceres clau" + "menuKeys": "Dreceres clau", + "submitButton": "Envia el botó" } diff --git a/translations/cy.json b/translations/cy.json index e0c3f167e..40b88e4e9 100644 --- a/translations/cy.json +++ b/translations/cy.json @@ -426,5 +426,6 @@ "menuRoles": "Rolau", "menuSkills": "Medrau", "menuLogout": "Allgofnodi", - "menuKeys": "Llwybrau byr allweddol" + "menuKeys": "Llwybrau byr allweddol", + "submitButton": "Cyflwyno botwm" } diff --git a/translations/de.json b/translations/de.json index 70427d027..370a2a200 100644 --- a/translations/de.json +++ b/translations/de.json @@ -426,5 +426,6 @@ "menuRoles": "Rollen", "menuSkills": "Kompetenzen", "menuLogout": "Ausloggen", - "menuKeys": "Schlüsselverknüpfungen" + "menuKeys": "Schlüsselverknüpfungen", + "submitButton": "Button einreichen" } diff --git a/translations/en.json b/translations/en.json index c9ef9a103..a08b8fe22 100644 --- a/translations/en.json +++ b/translations/en.json @@ -426,5 +426,6 @@ "menuRoles": "Roles", "menuSkills": "Skills", "menuLogout": "Logout", - "menuKeys": "Key Shortcuts" + "menuKeys": "Key Shortcuts", + "submitButton": "Submit button" } diff --git a/translations/es.json b/translations/es.json index 29068b653..f2a40a394 100644 --- a/translations/es.json +++ b/translations/es.json @@ -426,5 +426,6 @@ "menuRoles": "Roles", "menuSkills": "Habilidades", "menuLogout": "Cerrar sesión", - "menuKeys": "Atajos clave" + "menuKeys": "Atajos clave", + "submitButton": "Botón de enviar" } diff --git a/translations/fr.json b/translations/fr.json index 42e0c1a4b..396c1e95f 100644 --- a/translations/fr.json +++ b/translations/fr.json @@ -426,5 +426,6 @@ "menuRoles": "Les rôles", "menuSkills": "Compétences", "menuLogout": "Se déconnecter", - "menuKeys": "Raccourcis clés" + "menuKeys": "Raccourcis clés", + "submitButton": "Bouton de soumission" } diff --git a/translations/ga.json b/translations/ga.json index 82ddab85a..6d2be022f 100644 --- a/translations/ga.json +++ b/translations/ga.json @@ -426,5 +426,6 @@ "menuRoles": "Róil", "menuSkills": "Scileanna", "menuLogout": "Logáil Amach", - "menuKeys": "Príomh-aicearraí" + "menuKeys": "Príomh-aicearraí", + "submitButton": "Cuir an cnaipe isteach" } diff --git a/translations/hi.json b/translations/hi.json index 853b74725..5f4880867 100644 --- a/translations/hi.json +++ b/translations/hi.json @@ -426,5 +426,6 @@ "menuRoles": "भूमिकाएँ", "menuSkills": "कौशल", "menuLogout": "लॉग आउट", - "menuKeys": "कुंजी शॉर्टकट" + "menuKeys": "कुंजी शॉर्टकट", + "submitButton": "जमा करने वाला बटन" } diff --git a/translations/it.json b/translations/it.json index b7bee1906..0b055fed6 100644 --- a/translations/it.json +++ b/translations/it.json @@ -426,5 +426,6 @@ "menuRoles": "Ruoli", "menuSkills": "Competenze", "menuLogout": "Disconnettersi", - "menuKeys": "Scorciatoie chiave" + "menuKeys": "Scorciatoie chiave", + "submitButton": "Invia il pulsante" } diff --git a/translations/ja.json b/translations/ja.json index 50273899d..359d700a9 100644 --- a/translations/ja.json +++ b/translations/ja.json @@ -426,5 +426,6 @@ "menuRoles": "役割", "menuSkills": "スキル", "menuLogout": "ログアウト", - "menuKeys": "キーショートカット" + "menuKeys": "キーショートカット", + "submitButton": "送信ボタン" } diff --git a/translations/ku.json b/translations/ku.json index 2595c9dea..88dae41be 100644 --- a/translations/ku.json +++ b/translations/ku.json @@ -426,5 +426,6 @@ "menuRoles": "Roles", "menuSkills": "Şarezayên", "menuLogout": "Derkeve", - "menuKeys": "Kurteyên Key" + "menuKeys": "Kurteyên Key", + "submitButton": "Bişkojka bişînin" } diff --git a/translations/oc.json b/translations/oc.json index adc35439b..d47e16d11 100644 --- a/translations/oc.json +++ b/translations/oc.json @@ -422,5 +422,6 @@ "menuRoles": "Roles", "menuSkills": "Skills", "menuLogout": "Logout", - "menuKeys": "Key Shortcuts" + "menuKeys": "Key Shortcuts", + "submitButton": "Submit button" } diff --git a/translations/pt.json b/translations/pt.json index 7e58dc8c5..1fb1437bf 100644 --- a/translations/pt.json +++ b/translations/pt.json @@ -426,5 +426,6 @@ "menuRoles": "Papéis", "menuSkills": "Habilidades", "menuLogout": "Sair", - "menuKeys": "Atalhos-chave" + "menuKeys": "Atalhos-chave", + "submitButton": "Botão de envio" } diff --git a/translations/ru.json b/translations/ru.json index 6e6e4102a..0d553527e 100644 --- a/translations/ru.json +++ b/translations/ru.json @@ -426,5 +426,6 @@ "menuRoles": "Роли", "menuSkills": "Навыки и умения", "menuLogout": "Выйти", - "menuKeys": "Клавичные ярлыки" + "menuKeys": "Клавичные ярлыки", + "submitButton": "Отправить кнопку" } diff --git a/translations/zh.json b/translations/zh.json index 38e8ce523..348b82b10 100644 --- a/translations/zh.json +++ b/translations/zh.json @@ -426,5 +426,6 @@ "menuRoles": "角色", "menuSkills": "技能", "menuLogout": "登出", - "menuKeys": "关键捷径" + "menuKeys": "关键捷径", + "submitButton": "提交按钮" } diff --git a/webapp_accesskeys.py b/webapp_accesskeys.py index 647cfbeb8..fa722f298 100644 --- a/webapp_accesskeys.py +++ b/webapp_accesskeys.py @@ -63,12 +63,15 @@ def htmlAccessKeys(cssCache: {}, baseDir: str, accessKeysForm += '
    \n' + timelineKey = accessKeys['menuTimeline'] + submitKey = accessKeys['submitButton'] accessKeysForm += \ '
    \n' + \ ' \n' + \ - ' \n
    \n' accessKeysForm += '
    \n' diff --git a/webapp_search.py b/webapp_search.py index 048ba1647..284c86425 100644 --- a/webapp_search.py +++ b/webapp_search.py @@ -319,7 +319,7 @@ def htmlSearchEmojiTextEntry(cssCache: {}, translate: {}, def htmlSearch(cssCache: {}, translate: {}, baseDir: str, path: str, domain: str, defaultTimeline: str, theme: str, - textModeBanner: str) -> str: + textModeBanner: str, accessKeys: {}) -> str: """Search called from the timeline icon """ actor = path.replace('/search', '') @@ -347,12 +347,14 @@ def htmlSearch(cssCache: {}, translate: {}, textModeBannerStr = '' if os.path.isfile(searchBannerFilename): + timelineKey = accessKeys['menuTimeline'] usersPath = '/users/' + searchNickname followStr += \ '
    \n' + textModeBannerStr + \ '\n' + translate['Switch to timeline view'] + '" ' + \ + 'accesskey="' + timelineKey + '">\n' followStr += '\n' + \ '
    \n' @@ -370,8 +372,10 @@ def htmlSearch(cssCache: {}, translate: {}, followStr += \ ' \n' followStr += '
    \n' + submitKey = accessKeys['submitButton'] followStr += ' \n' + 'name="submitSearch" accesskey="' + submitKey + '">' + \ + translate['Submit'] + '\n' followStr += ' \n' followStr += '

    ' + \ htmlHashTagSwarm(baseDir, actor, translate) + '

    \n' From 4b904c8f335145c99cd59d410304b6e735f89ac3 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 23 Apr 2021 13:04:42 +0100 Subject: [PATCH 31/54] More key shortcuts --- daemon.py | 29 ++++++++++++++++++++++++++--- translations/ar.json | 11 ++++++++++- translations/ca.json | 11 ++++++++++- translations/cy.json | 11 ++++++++++- translations/de.json | 11 ++++++++++- translations/en.json | 11 ++++++++++- translations/es.json | 11 ++++++++++- translations/fr.json | 11 ++++++++++- translations/ga.json | 11 ++++++++++- translations/hi.json | 11 ++++++++++- translations/it.json | 11 ++++++++++- translations/ja.json | 11 ++++++++++- translations/ku.json | 11 ++++++++++- translations/oc.json | 11 ++++++++++- translations/pt.json | 11 ++++++++++- translations/ru.json | 11 ++++++++++- translations/zh.json | 11 ++++++++++- webapp_person_options.py | 40 +++++++++++++++++++++++++++------------- webapp_profile.py | 25 ++++++++++++++++--------- 19 files changed, 229 insertions(+), 41 deletions(-) diff --git a/daemon.py b/daemon.py index 193ea3a8f..fa340b2af 100644 --- a/daemon.py +++ b/daemon.py @@ -2845,6 +2845,11 @@ class PubServer(BaseHTTPRequestHandler): showPublishedDateOnly = self.server.showPublishedDateOnly allowLocalNetworkAccess = \ self.server.allowLocalNetworkAccess + + accessKeys = self.server.accessKeys + if self.server.keyShortcuts.get(nickname): + accessKeys = self.server.keyShortcuts[nickname] + profileStr = \ htmlProfileAfterSearch(self.server.cssCache, self.server.recentPostsCache, @@ -2867,7 +2872,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.defaultTimeline, self.server.peertubeInstances, allowLocalNetworkAccess, - self.server.themeName) + self.server.themeName, + accessKeys) if profileStr: msg = profileStr.encode('utf-8') msglen = len(msg) @@ -5718,6 +5724,13 @@ class PubServer(BaseHTTPRequestHandler): optionsActor, optionsProfileUrl, self.server.personCache, 5) + accessKeys = self.server.accessKeys + if '/users/' in path: + nickname = path.split('/users/')[1] + if '/' in nickname: + nickname = nickname.split('/')[0] + if self.server.keyShortcuts.get(nickname): + accessKeys = self.server.keyShortcuts[nickname] msg = htmlPersonOptions(self.server.defaultTimeline, self.server.cssCache, self.server.translate, @@ -5740,7 +5753,8 @@ class PubServer(BaseHTTPRequestHandler): movedTo, alsoKnownAs, self.server.textModeBanner, self.server.newsInstance, - authorized).encode('utf-8') + authorized, + accessKeys).encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, cookie, callingDomain) @@ -14658,6 +14672,14 @@ def runDaemon(brochMode: bool, # key shortcuts SHIFT + ALT + [key] httpd.accessKeys = { 'submitButton': 'y', + 'followButton': 'f', + 'blockButton': 'b', + 'infoButton': 'i', + 'snoozeButton': 's', + 'reportButton': 'r', + 'viewButton': 'v', + 'enterPetname': 'p', + 'enterNotes': 'n', 'menuTimeline': 't', 'menuEdit': 'e', 'menuProfile': 'p', @@ -14673,7 +14695,8 @@ def runDaemon(brochMode: bool, 'menuBlogs': 'b', 'menuNewswire': 'w', 'menuLinks': 'l', - 'menuModeration': 'm', + 'menuMedia': 'm', + 'menuModeration': 'o', 'menuFollowing': 'f', 'menuFollowers': 'g', 'menuRoles': 'o', diff --git a/translations/ar.json b/translations/ar.json index 5eb4c3dff..00bed874d 100644 --- a/translations/ar.json +++ b/translations/ar.json @@ -427,5 +427,14 @@ "menuSkills": "مهارات", "menuLogout": "تسجيل خروج", "menuKeys": "الاختصارات الرئيسية", - "submitButton": "زر الإرسال" + "submitButton": "زر الإرسال", + "menuMedia": "وسائط", + "followButton": "زر متابعة / متابعة", + "blockButton": "زر كتلة", + "infoButton": "زر المعلومات", + "snoozeButton": "زر الغفوة", + "reportButton": "زر تقرير", + "viewButton": "عرض زر", + "enterPetname": "أدخل PETNAME", + "enterNotes": "أدخل الملاحظات" } diff --git a/translations/ca.json b/translations/ca.json index 86658f70c..9c6f0ecdb 100644 --- a/translations/ca.json +++ b/translations/ca.json @@ -427,5 +427,14 @@ "menuSkills": "Habilitats", "menuLogout": "Tancar sessió", "menuKeys": "Dreceres clau", - "submitButton": "Envia el botó" + "submitButton": "Envia el botó", + "menuMedia": "Medis de comunicació", + "followButton": "Seguiu / no seguit", + "blockButton": "Botó de bloc", + "infoButton": "Botó d'informació", + "snoozeButton": "Botó de snooze", + "reportButton": "Botó d'informe", + "viewButton": "Botó Veure", + "enterPetname": "Introduïu PETNAME", + "enterNotes": "Introduïu notes" } diff --git a/translations/cy.json b/translations/cy.json index 40b88e4e9..3ffc9c8f9 100644 --- a/translations/cy.json +++ b/translations/cy.json @@ -427,5 +427,14 @@ "menuSkills": "Medrau", "menuLogout": "Allgofnodi", "menuKeys": "Llwybrau byr allweddol", - "submitButton": "Cyflwyno botwm" + "submitButton": "Cyflwyno botwm", + "menuMedia": "Chyfryngau", + "followButton": "Dilynwch / Peidiwch â Dilynwch y botwm", + "blockButton": "Botwm bloc", + "infoButton": "Botwm info", + "snoozeButton": "Botwm Snooze", + "reportButton": "Botwm adroddiadau", + "viewButton": "Gweld y botwm", + "enterPetname": "Rhowch enw PETName", + "enterNotes": "Rhowch nodiadau" } diff --git a/translations/de.json b/translations/de.json index 370a2a200..2473a4be4 100644 --- a/translations/de.json +++ b/translations/de.json @@ -427,5 +427,14 @@ "menuSkills": "Kompetenzen", "menuLogout": "Ausloggen", "menuKeys": "Schlüsselverknüpfungen", - "submitButton": "Button einreichen" + "submitButton": "Button einreichen", + "menuMedia": "Medien", + "followButton": "Folgen / folgen Sie nicht der Taste", + "blockButton": "Blockknopf", + "infoButton": "Info-Taste", + "snoozeButton": "Schlummertaste", + "reportButton": "Berichtsknopf", + "viewButton": "Schaltfläche anzeigen", + "enterPetname": "Petname eingeben", + "enterNotes": "Notizen eingeben" } diff --git a/translations/en.json b/translations/en.json index a08b8fe22..7dbe1d4e4 100644 --- a/translations/en.json +++ b/translations/en.json @@ -427,5 +427,14 @@ "menuSkills": "Skills", "menuLogout": "Logout", "menuKeys": "Key Shortcuts", - "submitButton": "Submit button" + "submitButton": "Submit button", + "menuMedia": "Media", + "followButton": "Follow/unfollow button", + "blockButton": "Block button", + "infoButton": "Info button", + "snoozeButton": "Snooze button", + "reportButton": "Report button", + "viewButton": "View button", + "enterPetname": "Enter petname", + "enterNotes": "Enter notes" } diff --git a/translations/es.json b/translations/es.json index f2a40a394..b54ee96fe 100644 --- a/translations/es.json +++ b/translations/es.json @@ -427,5 +427,14 @@ "menuSkills": "Habilidades", "menuLogout": "Cerrar sesión", "menuKeys": "Atajos clave", - "submitButton": "Botón de enviar" + "submitButton": "Botón de enviar", + "menuMedia": "Medios de comunicación", + "followButton": "Botón de seguimiento / dejo", + "blockButton": "Botón de bloqueo", + "infoButton": "Botón de información", + "snoozeButton": "El botón de dormitar", + "reportButton": "Botón de informe", + "viewButton": "Botón de vista", + "enterPetname": "Entrar en nombre de pettname", + "enterNotes": "Ingresar notas" } diff --git a/translations/fr.json b/translations/fr.json index 396c1e95f..7615ea636 100644 --- a/translations/fr.json +++ b/translations/fr.json @@ -427,5 +427,14 @@ "menuSkills": "Compétences", "menuLogout": "Se déconnecter", "menuKeys": "Raccourcis clés", - "submitButton": "Bouton de soumission" + "submitButton": "Bouton de soumission", + "menuMedia": "Médias", + "followButton": "Suivez / Bouton Suivi", + "blockButton": "Bouton de bloc", + "infoButton": "Bouton info", + "snoozeButton": "Le bouton de la sieste", + "reportButton": "Bouton de rapport", + "viewButton": "Bouton d'affichage", + "enterPetname": "Entrez PETNAME", + "enterNotes": "Faire entrer des notes" } diff --git a/translations/ga.json b/translations/ga.json index 6d2be022f..6e601cc41 100644 --- a/translations/ga.json +++ b/translations/ga.json @@ -427,5 +427,14 @@ "menuSkills": "Scileanna", "menuLogout": "Logáil Amach", "menuKeys": "Príomh-aicearraí", - "submitButton": "Cuir an cnaipe isteach" + "submitButton": "Cuir an cnaipe isteach", + "menuMedia": "Na meáin", + "followButton": "Lean / Cnaipe Unurollow", + "blockButton": "Cnaipe bloc", + "infoButton": "Cnaipe Info", + "snoozeButton": "Cnaipe snooze", + "reportButton": "Cnaipe Tuairisce", + "viewButton": "Féach an cnaipe", + "enterPetname": "Cuir isteach PetName", + "enterNotes": "Cuir nótaí isteach" } diff --git a/translations/hi.json b/translations/hi.json index 5f4880867..5e8b633c4 100644 --- a/translations/hi.json +++ b/translations/hi.json @@ -427,5 +427,14 @@ "menuSkills": "कौशल", "menuLogout": "लॉग आउट", "menuKeys": "कुंजी शॉर्टकट", - "submitButton": "जमा करने वाला बटन" + "submitButton": "जमा करने वाला बटन", + "menuMedia": "मीडिया", + "followButton": "फॉलो / अनफ़ॉलो बटन", + "blockButton": "ब्लॉक बटन", + "infoButton": "जानकारी बटन", + "snoozeButton": "अलार्म को थोड़ी देर बंद करने वाला बटन", + "reportButton": "रिपोर्ट बटन", + "viewButton": "देखें बटन", + "enterPetname": "PETNAME दर्ज करें", + "enterNotes": "नोट्स दर्ज करें" } diff --git a/translations/it.json b/translations/it.json index 0b055fed6..58753c309 100644 --- a/translations/it.json +++ b/translations/it.json @@ -427,5 +427,14 @@ "menuSkills": "Competenze", "menuLogout": "Disconnettersi", "menuKeys": "Scorciatoie chiave", - "submitButton": "Invia il pulsante" + "submitButton": "Invia il pulsante", + "menuMedia": "Media", + "followButton": "Segui il pulsante Segui / Unfollow", + "blockButton": "Blocco pulsante", + "infoButton": "Pulsante info", + "snoozeButton": "Pulsante snooze.", + "reportButton": "Pulsante report.", + "viewButton": "Visualizza il pulsante", + "enterPetname": "Inserisci PetName", + "enterNotes": "Inserisci le note" } diff --git a/translations/ja.json b/translations/ja.json index 359d700a9..7d9b3dc5f 100644 --- a/translations/ja.json +++ b/translations/ja.json @@ -427,5 +427,14 @@ "menuSkills": "スキル", "menuLogout": "ログアウト", "menuKeys": "キーショートカット", - "submitButton": "送信ボタン" + "submitButton": "送信ボタン", + "menuMedia": "メディア", + "followButton": "フォロー/フォローダウンボタン", + "blockButton": "ブロックボタン", + "infoButton": "情報ボタン", + "snoozeButton": "スヌーズボタン", + "reportButton": "レポートボタン", + "viewButton": "ボタンを見る", + "enterPetname": "PetNameを入力してください", + "enterNotes": "ノートを入力してください" } diff --git a/translations/ku.json b/translations/ku.json index 88dae41be..6675c75e0 100644 --- a/translations/ku.json +++ b/translations/ku.json @@ -427,5 +427,14 @@ "menuSkills": "Şarezayên", "menuLogout": "Derkeve", "menuKeys": "Kurteyên Key", - "submitButton": "Bişkojka bişînin" + "submitButton": "Bişkojka bişînin", + "menuMedia": "Medya", + "followButton": "Bişkojka bişopînin / Nexşe", + "blockButton": "Bişkojka Block", + "infoButton": "Bişkoja INFO", + "snoozeButton": "Bişkojka Snooze", + "reportButton": "Bişkoja Report", + "viewButton": "Bişkoja View", + "enterPetname": "Porê binivîse", + "enterNotes": "Nîşan binivîse" } diff --git a/translations/oc.json b/translations/oc.json index d47e16d11..7db236cfd 100644 --- a/translations/oc.json +++ b/translations/oc.json @@ -423,5 +423,14 @@ "menuSkills": "Skills", "menuLogout": "Logout", "menuKeys": "Key Shortcuts", - "submitButton": "Submit button" + "submitButton": "Submit button", + "menuMedia": "Media", + "followButton": "Follow/unfollow button", + "blockButton": "Block button", + "infoButton": "Info button", + "snoozeButton": "Snooze button", + "reportButton": "Report button", + "viewButton": "View button", + "enterPetname": "Enter petname", + "enterNotes": "Enter notes" } diff --git a/translations/pt.json b/translations/pt.json index 1fb1437bf..97966a384 100644 --- a/translations/pt.json +++ b/translations/pt.json @@ -427,5 +427,14 @@ "menuSkills": "Habilidades", "menuLogout": "Sair", "menuKeys": "Atalhos-chave", - "submitButton": "Botão de envio" + "submitButton": "Botão de envio", + "menuMedia": "meios de comunicação", + "followButton": "Siga / Deixar botão", + "blockButton": "Botão de bloco", + "infoButton": "Botão de informação", + "snoozeButton": "Botão Snooze", + "reportButton": "Botão de relatório", + "viewButton": "Botão de visualização", + "enterPetname": "Digite Petname", + "enterNotes": "Digite notas" } diff --git a/translations/ru.json b/translations/ru.json index 0d553527e..06b2994fc 100644 --- a/translations/ru.json +++ b/translations/ru.json @@ -427,5 +427,14 @@ "menuSkills": "Навыки и умения", "menuLogout": "Выйти", "menuKeys": "Клавичные ярлыки", - "submitButton": "Отправить кнопку" + "submitButton": "Отправить кнопку", + "menuMedia": "СМИ", + "followButton": "Следуйте / отписаться кнопка", + "blockButton": "Кнопка блокировки", + "infoButton": "Информация Кнопка", + "snoozeButton": "Кнопка сножения", + "reportButton": "Кнопка отчета", + "viewButton": "Кнопка просмотра", + "enterPetname": "Введите petname", + "enterNotes": "Введите ноты" } diff --git a/translations/zh.json b/translations/zh.json index 348b82b10..9fa5d1d4f 100644 --- a/translations/zh.json +++ b/translations/zh.json @@ -427,5 +427,14 @@ "menuSkills": "技能", "menuLogout": "登出", "menuKeys": "关键捷径", - "submitButton": "提交按钮" + "submitButton": "提交按钮", + "menuMedia": "媒体", + "followButton": "关注/取消关注按钮", + "blockButton": "块按钮", + "infoButton": "信息按钮", + "snoozeButton": "贪睡按钮", + "reportButton": "报告按钮", + "viewButton": "查看按钮", + "enterPetname": "进入宠物名", + "enterNotes": "输入笔记" } diff --git a/webapp_person_options.py b/webapp_person_options.py index 8019a87c1..5bd87de76 100644 --- a/webapp_person_options.py +++ b/webapp_person_options.py @@ -54,7 +54,8 @@ def htmlPersonOptions(defaultTimeline: str, alsoKnownAs: [], textModeBanner: str, newsInstance: bool, - authorized: bool) -> str: + authorized: bool, + accessKeys: {}) -> str: """Show options for a person: view/follow/block/report """ optionsDomain, optionsPort = getDomainFromActor(optionsActor) @@ -234,7 +235,8 @@ def htmlPersonOptions(defaultTimeline: str, optionsStr += \ ' ' + translate['Petname'] + ': \n' + \ ' \n' \ + petname + '" ' + \ + 'accesskey="' + accessKeys['enterPetname'] + '">\n' \ '
    \n' @@ -324,40 +326,51 @@ def htmlPersonOptions(defaultTimeline: str, if authorized and originPathStr == '/users/' + nickname: optionsStr += \ ' \n' + 'class="buttonIcon" name="submitBack" ' + \ + 'accesskey="' + accessKeys['menuTimeline'] + '">' + \ + translate['Go Back'] + '\n' else: optionsStr += \ ' \n' if authorized: optionsStr += \ - ' \n' optionsStr += donateStr if authorized: optionsStr += \ ' \n' + followStr + '" accesskey="' + accessKeys['followButton'] + '">' + \ + translate[followStr] + '\n' optionsStr += \ ' \n' + blockStr + '" accesskey="' + accessKeys['blockButton'] + '">' + \ + translate[blockStr] + '\n' optionsStr += \ - ' \n' optionsStr += \ ' \n' optionsStr += \ ' \n' + 'name="submitReport" accesskey="' + \ + accessKeys['reportButton'] + '">' + \ + translate['Report'] + '\n' if isModerator(baseDir, nickname): optionsStr += \ ' \n' personNotes = '' @@ -376,7 +389,8 @@ def htmlPersonOptions(defaultTimeline: str, translate['Submit'] + '
    \n' optionsStr += \ ' \n' optionsStr += ' \n' diff --git a/webapp_profile.py b/webapp_profile.py index c9112ae98..b8eb9d984 100644 --- a/webapp_profile.py +++ b/webapp_profile.py @@ -67,7 +67,8 @@ def htmlProfileAfterSearch(cssCache: {}, defaultTimeline: str, peertubeInstances: [], allowLocalNetworkAccess: bool, - themeName: str) -> str: + themeName: str, + accessKeys: {}) -> str: """Show a profile page after a search for a fediverse address """ if hasUsersPath(profileHandle) or '/@' in profileHandle: @@ -255,7 +256,7 @@ def htmlProfileAfterSearch(cssCache: {}, profileDescriptionShort, avatarUrl, imageUrl, movedTo, profileJson['id'], - alsoKnownAs) + alsoKnownAs, accessKeys) domainFull = getFullDomain(domain, port) @@ -276,10 +277,12 @@ def htmlProfileAfterSearch(cssCache: {}, ' \n' profileStr += \ - ' \n' profileStr += \ - ' \n' profileStr += ' \n' profileStr += ' \n' @@ -331,14 +334,16 @@ def _getProfileHeader(baseDir: str, httpPrefix: str, loginButton: str, avatarUrl: str, theme: str, movedTo: str, alsoKnownAs: [], - pinnedContent) -> str: + pinnedContent: str, + accessKeys: {}) -> str: """The header of the profile screen, containing background image and avatar """ htmlStr = '\n\n
    \n' htmlStr += ' \n' + translate['Switch to timeline view'] + '" ' + \ + 'accesskey="' + accessKeys['menuTimeline'] + '">\n' htmlStr += ' \n' @@ -411,14 +416,16 @@ def _getProfileHeaderAfterSearch(baseDir: str, profileDescriptionShort: str, avatarUrl: str, imageUrl: str, movedTo: str, actor: str, - alsoKnownAs: []) -> str: + alsoKnownAs: [], + accessKeys: {}) -> str: """The header of a searched for handle, containing background image and avatar """ htmlStr = '\n\n
    \n' htmlStr += ' \n' + translate['Switch to timeline view'] + '" ' + \ + 'accesskey="' + accessKeys['menuTimeline'] + '">\n' htmlStr += ' \n' @@ -723,7 +730,7 @@ def htmlProfile(rssIconAtTop: bool, profileDescriptionShort, loginButton, avatarUrl, theme, movedTo, alsoKnownAs, - pinnedContent) + pinnedContent, accessKeys) # keyboard navigation userPathStr = '/users/' + nickname From 5d4ed5b7418cb02c30cf96ada93948eecdf79adc Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 23 Apr 2021 13:24:34 +0100 Subject: [PATCH 32/54] Key shortcut to media timeline --- webapp_headerbuttons.py | 7 +++++-- webapp_timeline.py | 7 ++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/webapp_headerbuttons.py b/webapp_headerbuttons.py index 85c2d9fb3..c277a3511 100644 --- a/webapp_headerbuttons.py +++ b/webapp_headerbuttons.py @@ -43,7 +43,8 @@ def headerButtonsTimeline(defaultTimeline: str, calendarPath: str, calendarImage: str, followApprovals: str, - iconsAsButtons: bool) -> str: + iconsAsButtons: bool, + accessKeys: {}) -> str: """Returns the header at the top of the timeline, containing buttons for inbox, outbox, search, calendar, etc """ @@ -53,7 +54,9 @@ def headerButtonsTimeline(defaultTimeline: str, if defaultTimeline == 'tlmedia': tlStr += \ '' elif defaultTimeline == 'tlblogs': diff --git a/webapp_timeline.py b/webapp_timeline.py index 2298dd019..10b9748bf 100644 --- a/webapp_timeline.py +++ b/webapp_timeline.py @@ -269,7 +269,8 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, # show follow approvals icon followApprovals = \ '' + \ + '/followers#buttonheader" ' + \ + 'accesskey="' + accessKeys['followButton'] + '">' + \ '' + \
                         translate['Approve follow requests'] + \
@@ -515,7 +516,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
                                   domain, timelineStartTime,
                                   newCalendarEvent, calendarPath,
                                   calendarImage, followApprovals,
-                                  iconsAsButtons)
+                                  iconsAsButtons, accessKeys)
 
     # start the timeline
     tlStr += '<table class=\n' @@ -555,7 +556,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, domain, timelineStartTime, newCalendarEvent, calendarPath, calendarImage, followApprovals, - iconsAsButtons) + iconsAsButtons, accessKeys) tlStr += '
    \n' From 898af44e8b73108f133748b80aa788bda0ce153b Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 23 Apr 2021 13:31:20 +0100 Subject: [PATCH 33/54] Key shortcut to media timeline --- webapp_headerbuttons.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/webapp_headerbuttons.py b/webapp_headerbuttons.py index c277a3511..49ab245cd 100644 --- a/webapp_headerbuttons.py +++ b/webapp_headerbuttons.py @@ -105,7 +105,9 @@ def headerButtonsTimeline(defaultTimeline: str, if not minimal and not featuresHeader: tlStr += \ '' else: From 9b0a41a2b79b9d8e0d4b114d65799ad7f2b69f20 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 23 Apr 2021 14:20:28 +0100 Subject: [PATCH 34/54] Page up and down key shortcuts --- daemon.py | 2 ++ webapp_timeline.py | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/daemon.py b/daemon.py index fa340b2af..0696f52c8 100644 --- a/daemon.py +++ b/daemon.py @@ -14671,6 +14671,8 @@ def runDaemon(brochMode: bool, # key shortcuts SHIFT + ALT + [key] httpd.accessKeys = { + 'Page up': '.', + 'Page down': ',', 'submitButton': 'y', 'followButton': 'f', 'blockButton': 'b', diff --git a/webapp_timeline.py b/webapp_timeline.py index 10b9748bf..2ee1a7ffd 100644 --- a/webapp_timeline.py +++ b/webapp_timeline.py @@ -661,7 +661,8 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, '
    \n' + \ ' ' + \ + '' + \
             translate['Page up'] + '\n' + \ @@ -754,7 +755,8 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, '
    \n' + \ ' ' + \ + '' + \
             translate['Page down'] + '\n' + \ From b5c5a1c34fe11db9720585ad6028fcad61ec52cb Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 23 Apr 2021 14:22:36 +0100 Subject: [PATCH 35/54] Swap keys --- daemon.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/daemon.py b/daemon.py index 0696f52c8..ed60e957f 100644 --- a/daemon.py +++ b/daemon.py @@ -14671,8 +14671,8 @@ def runDaemon(brochMode: bool, # key shortcuts SHIFT + ALT + [key] httpd.accessKeys = { - 'Page up': '.', - 'Page down': ',', + 'Page up': ',', + 'Page down': '.', 'submitButton': 'y', 'followButton': 'f', 'blockButton': 'b', From 1d6f42c263da6e0d103609a00160d75cf8d72abf Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 23 Apr 2021 15:21:57 +0100 Subject: [PATCH 36/54] Receive changes to key shortcuts --- daemon.py | 105 +++++++++++++++++++++++++++++++++++++++++++ webapp_accesskeys.py | 6 ++- 2 files changed, 110 insertions(+), 1 deletion(-) diff --git a/daemon.py b/daemon.py index ed60e957f..045cd84b3 100644 --- a/daemon.py +++ b/daemon.py @@ -1802,6 +1802,87 @@ class PubServer(BaseHTTPRequestHandler): self.server.POSTbusy = False return + def _keyShortcuts(self, path: str, + callingDomain: str, cookie: str, + baseDir: str, httpPrefix: str, nickname: str, + domain: str, domainFull: str, port: int, + onionDomain: str, i2pDomain: str, + debug: bool, accessKeys: {}) -> None: + """Receive POST from webapp_accesskeys + """ + usersPath = path.split('/changeAccessKeys')[0] + originPathStr = httpPrefix + '://' + domainFull + usersPath + length = int(self.headers['Content-length']) + + try: + accessKeysParams = self.rfile.read(length).decode('utf-8') + except SocketError as e: + if e.errno == errno.ECONNRESET: + print('WARN: POST accessKeysParams ' + + 'connection reset by peer') + else: + print('WARN: POST accessKeysParams socket error') + self.send_response(400) + self.end_headers() + self.server.POSTbusy = False + return + except ValueError as e: + print('ERROR: POST accessKeysParams rfile.read failed') + print(e) + self.send_response(400) + self.end_headers() + self.server.POSTbusy = False + return + accessKeysParams = \ + urllib.parse.unquote_plus(accessKeysParams) + + # key shortcuts screen, back button + # See htmlAccessKeys + if '&submitAccessKeysCancel=' in accessKeysParams or \ + '&submitAccessKeys=' not in accessKeysParams: + if callingDomain.endswith('.onion') and onionDomain: + originPathStr = 'http://' + onionDomain + usersPath + elif callingDomain.endswith('.i2p') and i2pDomain: + originPathStr = 'http://' + i2pDomain + usersPath + self._redirect_headers(originPathStr, cookie, callingDomain) + self.server.POSTbusy = False + return + + saveKeys = False + accessKeysTemplate = self.server.accessKeys + for variableName, key in accessKeysTemplate.items(): + if not accessKeys.get(variableName): + accessKeys[variableName] = accessKeysTemplate[variableName] + + variableName2 = variableName.replace(' ', '_') + if variableName2 in accessKeysParams: + newKey = accessKeysParams.split(variableName2 + '=')[1] + if '&' in newKey: + newKey = newKey.split('&')[0] + if newKey: + if len(newKey) > 1: + newKey = newKey[0] + if newKey != accessKeys[variableName]: + accessKeys[variableName] = newKey + saveKeys = True + + if saveKeys: + accessKeysFilename = \ + baseDir + '/accounts/' + nickname + '@' + domain + \ + '/accessKeys.json' + saveJson(accessKeys, accessKeysFilename) + if not self.server.keyShortcuts.get(nickname): + self.server.keyShortcuts[nickname] = accessKeys.copy() + + # redirect back from key shortcuts screen + if callingDomain.endswith('.onion') and onionDomain: + originPathStr = 'http://' + onionDomain + usersPath + elif callingDomain.endswith('.i2p') and i2pDomain: + originPathStr = 'http://' + i2pDomain + usersPath + self._redirect_headers(originPathStr, cookie, callingDomain) + self.server.POSTbusy = False + return + def _personOptions(self, path: str, callingDomain: str, cookie: str, baseDir: str, httpPrefix: str, @@ -14192,6 +14273,30 @@ class PubServer(BaseHTTPRequestHandler): self.server.debug) return + # Change the key shortcuts + if usersInPath and \ + self.path.endswith('/changeAccessKeys'): + nickname = self.path.split('/users/')[1] + if '/' in nickname: + nickname = nickname.split('/')[0] + + accessKeys = self.server.accessKeys + if self.server.keyShortcuts.get(nickname): + accessKeys = self.server.keyShortcuts[nickname] + self._keyShortcuts(self.path, + callingDomain, cookie, + self.server.baseDir, + self.server.httpPrefix, + nickname, + self.server.domain, + self.server.domainFull, + self.server.port, + self.server.onionDomain, + self.server.i2pDomain, + self.server.debug, + accessKeys) + return + self._benchmarkPOSTtimings(POSTstartTime, POSTtimings, 14) # receive different types of post created by htmlNewPost diff --git a/webapp_accesskeys.py b/webapp_accesskeys.py index fa722f298..ef491e59f 100644 --- a/webapp_accesskeys.py +++ b/webapp_accesskeys.py @@ -90,8 +90,12 @@ def htmlAccessKeys(cssCache: {}, baseDir: str, translate[variableName] + '' if accessKeys.get(variableName): key = accessKeys[variableName] + if len(key) > 1: + key = key[0] keyStr += \ - '
    \n' accessKeysForm += keyStr From 4f29cd13c5ae843ce7afb9a0962fd20960ddf77b Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 23 Apr 2021 15:40:42 +0100 Subject: [PATCH 37/54] Create key shortcuts for account --- daemon.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/daemon.py b/daemon.py index 045cd84b3..7806fef5e 100644 --- a/daemon.py +++ b/daemon.py @@ -14280,9 +14280,11 @@ class PubServer(BaseHTTPRequestHandler): if '/' in nickname: nickname = nickname.split('/')[0] - accessKeys = self.server.accessKeys - if self.server.keyShortcuts.get(nickname): - accessKeys = self.server.keyShortcuts[nickname] + if not self.server.keyShortcuts.get(nickname): + accessKeys = self.server.accessKeys + self.server.keyShortcuts[nickname] = accessKeys.copy() + accessKeys = self.server.keyShortcuts[nickname] + self._keyShortcuts(self.path, callingDomain, cookie, self.server.baseDir, From 556885b8ba3f91d638e55aef2ae553cb42b8b8c0 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 23 Apr 2021 16:49:41 +0100 Subject: [PATCH 38/54] Debug --- daemon.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/daemon.py b/daemon.py index 7806fef5e..856b33a82 100644 --- a/daemon.py +++ b/daemon.py @@ -1835,7 +1835,7 @@ class PubServer(BaseHTTPRequestHandler): return accessKeysParams = \ urllib.parse.unquote_plus(accessKeysParams) - + print('accessKeysParams: ' + str(accessKeysParams)) # key shortcuts screen, back button # See htmlAccessKeys if '&submitAccessKeysCancel=' in accessKeysParams or \ @@ -1855,11 +1855,12 @@ class PubServer(BaseHTTPRequestHandler): accessKeys[variableName] = accessKeysTemplate[variableName] variableName2 = variableName.replace(' ', '_') - if variableName2 in accessKeysParams: + if variableName2 + '=' in accessKeysParams: newKey = accessKeysParams.split(variableName2 + '=')[1] if '&' in newKey: newKey = newKey.split('&')[0] if newKey: + print('accessKeysParams newKey: ' + str(newKey)) if len(newKey) > 1: newKey = newKey[0] if newKey != accessKeys[variableName]: From 5a28cd303b4b95d2a0035bfdfcc8f9774b22c04f Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 23 Apr 2021 16:57:29 +0100 Subject: [PATCH 39/54] Return from key shortcuts to default timeline --- daemon.py | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/daemon.py b/daemon.py index 856b33a82..df8a488ac 100644 --- a/daemon.py +++ b/daemon.py @@ -1807,11 +1807,13 @@ class PubServer(BaseHTTPRequestHandler): baseDir: str, httpPrefix: str, nickname: str, domain: str, domainFull: str, port: int, onionDomain: str, i2pDomain: str, - debug: bool, accessKeys: {}) -> None: + debug: bool, accessKeys: {}, + defaultTimeline: str) -> None: """Receive POST from webapp_accesskeys """ - usersPath = path.split('/changeAccessKeys')[0] - originPathStr = httpPrefix + '://' + domainFull + usersPath + usersPath = '/users/' + nickname + originPathStr = \ + httpPrefix + '://' + domainFull + usersPath + '/' + defaultTimeline length = int(self.headers['Content-length']) try: @@ -1835,15 +1837,17 @@ class PubServer(BaseHTTPRequestHandler): return accessKeysParams = \ urllib.parse.unquote_plus(accessKeysParams) - print('accessKeysParams: ' + str(accessKeysParams)) + # key shortcuts screen, back button # See htmlAccessKeys - if '&submitAccessKeysCancel=' in accessKeysParams or \ - '&submitAccessKeys=' not in accessKeysParams: + if 'submitAccessKeysCancel=' in accessKeysParams or \ + 'submitAccessKeys=' not in accessKeysParams: if callingDomain.endswith('.onion') and onionDomain: - originPathStr = 'http://' + onionDomain + usersPath + originPathStr = \ + 'http://' + onionDomain + usersPath + '/' + defaultTimeline elif callingDomain.endswith('.i2p') and i2pDomain: - originPathStr = 'http://' + i2pDomain + usersPath + originPathStr = \ + 'http://' + i2pDomain + usersPath + '/' + defaultTimeline self._redirect_headers(originPathStr, cookie, callingDomain) self.server.POSTbusy = False return @@ -1860,7 +1864,6 @@ class PubServer(BaseHTTPRequestHandler): if '&' in newKey: newKey = newKey.split('&')[0] if newKey: - print('accessKeysParams newKey: ' + str(newKey)) if len(newKey) > 1: newKey = newKey[0] if newKey != accessKeys[variableName]: @@ -1877,9 +1880,11 @@ class PubServer(BaseHTTPRequestHandler): # redirect back from key shortcuts screen if callingDomain.endswith('.onion') and onionDomain: - originPathStr = 'http://' + onionDomain + usersPath + originPathStr = \ + 'http://' + onionDomain + usersPath + '/' + defaultTimeline elif callingDomain.endswith('.i2p') and i2pDomain: - originPathStr = 'http://' + i2pDomain + usersPath + originPathStr = \ + 'http://' + i2pDomain + usersPath + '/' + defaultTimeline self._redirect_headers(originPathStr, cookie, callingDomain) self.server.POSTbusy = False return @@ -14297,7 +14302,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.onionDomain, self.server.i2pDomain, self.server.debug, - accessKeys) + accessKeys, + self.server.defaultTimeline) return self._benchmarkPOSTtimings(POSTstartTime, POSTtimings, 14) From 0f778b5d581fa34dda77275bf70be138b521a685 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 23 Apr 2021 17:07:26 +0100 Subject: [PATCH 40/54] Key shortcuts link --- webapp_column_left.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/webapp_column_left.py b/webapp_column_left.py index 70c9648c0..916ea2183 100644 --- a/webapp_column_left.py +++ b/webapp_column_left.py @@ -254,6 +254,10 @@ def getLeftColumnContent(baseDir: str, nickname: str, domainFull: str, if firstSeparatorAdded: htmlStr += separatorStr + htmlStr += \ + '' htmlStr += \ '' From 04b7ba00654f73eb0e5d247b95584bb613306818 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 23 Apr 2021 17:29:03 +0100 Subject: [PATCH 41/54] Key shortcut to key shortcuts --- daemon.py | 6 +++++- webapp_column_left.py | 10 ++++++---- webapp_frontscreen.py | 3 ++- webapp_profile.py | 2 +- webapp_timeline.py | 2 +- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/daemon.py b/daemon.py index df8a488ac..965595a98 100644 --- a/daemon.py +++ b/daemon.py @@ -11781,6 +11781,9 @@ class PubServer(BaseHTTPRequestHandler): self._404() self.server.GETbusy = False return + accessKeys = self.server.accessKeys + if self.server.keyShortcuts.get(nickname): + accessKeys = self.server.keyShortcuts[nickname] timelinePath = \ '/users/' + nickname + '/' + self.server.defaultTimeline iconsAsButtons = self.server.iconsAsButtons @@ -11795,7 +11798,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.rssIconAtTop, iconsAsButtons, defaultTimeline, - self.server.themeName).encode('utf-8') + self.server.themeName, + accessKeys).encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, cookie, callingDomain) self._write(msg) diff --git a/webapp_column_left.py b/webapp_column_left.py index 916ea2183..1c4af048a 100644 --- a/webapp_column_left.py +++ b/webapp_column_left.py @@ -68,7 +68,8 @@ def getLeftColumnContent(baseDir: str, nickname: str, domainFull: str, editor: bool, showBackButton: bool, timelinePath: str, rssIconAtTop: bool, showHeaderImage: bool, - frontPage: bool, theme: str) -> str: + frontPage: bool, theme: str, + accessKeys: {}) -> str: """Returns html content for the left column """ htmlStr = '' @@ -256,7 +257,8 @@ def getLeftColumnContent(baseDir: str, nickname: str, domainFull: str, htmlStr += separatorStr htmlStr += \ '' htmlStr += \ '\n' From 4c06b021194951c517fd60ac3f3fcd505d586b8c Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 23 Apr 2021 17:45:46 +0100 Subject: [PATCH 42/54] Singular --- webapp_column_left.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp_column_left.py b/webapp_column_left.py index 1c4af048a..d95a865d9 100644 --- a/webapp_column_left.py +++ b/webapp_column_left.py @@ -257,7 +257,7 @@ def getLeftColumnContent(baseDir: str, nickname: str, domainFull: str, htmlStr += separatorStr htmlStr += \ '' htmlStr += \ From e175bb207cd79db4d436dae2649c242792830565 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 23 Apr 2021 18:04:37 +0100 Subject: [PATCH 43/54] Key shortcuts on new post screen --- daemon.py | 29 ++++++++++++++++++++++++++--- webapp_create_post.py | 9 ++++++--- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/daemon.py b/daemon.py index 965595a98..f506adac0 100644 --- a/daemon.py +++ b/daemon.py @@ -2257,6 +2257,15 @@ class PubServer(BaseHTTPRequestHandler): if debug: print('Sending DM to ' + optionsActor) reportPath = path.replace('/personoptions', '') + '/newdm' + + accessKeys = self.server.accessKeys + if '/users/' in path: + nickname = path.split('/users/')[1] + if '/' in nickname: + nickname = nickname.split('/')[0] + if self.server.keyShortcuts.get(nickname): + accessKeys = self.server.keyShortcuts[nickname] + msg = htmlNewPost(self.server.cssCache, False, self.server.translate, baseDir, @@ -2270,7 +2279,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.defaultTimeline, self.server.newswire, self.server.themeName, - True).encode('utf-8') + True, accessKeys).encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, cookie, callingDomain) @@ -2357,6 +2366,15 @@ class PubServer(BaseHTTPRequestHandler): print('Reporting ' + optionsActor) reportPath = \ path.replace('/personoptions', '') + '/newreport' + + accessKeys = self.server.accessKeys + if '/users/' in path: + nickname = path.split('/users/')[1] + if '/' in nickname: + nickname = nickname.split('/')[0] + if self.server.keyShortcuts.get(nickname): + accessKeys = self.server.keyShortcuts[nickname] + msg = htmlNewPost(self.server.cssCache, False, self.server.translate, baseDir, @@ -2369,7 +2387,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.defaultTimeline, self.server.newswire, self.server.themeName, - True).encode('utf-8') + True, accessKeys).encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, cookie, callingDomain) @@ -10345,6 +10363,11 @@ class PubServer(BaseHTTPRequestHandler): break if isNewPostEndpoint: nickname = getNicknameFromActor(path) + + accessKeys = self.server.accessKeys + if self.server.keyShortcuts.get(nickname): + accessKeys = self.server.keyShortcuts[nickname] + msg = htmlNewPost(self.server.cssCache, mediaInstance, translate, @@ -10359,7 +10382,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.defaultTimeline, self.server.newswire, self.server.themeName, - noDropDown).encode('utf-8') + noDropDown, accessKeys).encode('utf-8') if not msg: print('Error replying to ' + inReplyToUrl) self._404() diff --git a/webapp_create_post.py b/webapp_create_post.py index c540f49a1..904bcca63 100644 --- a/webapp_create_post.py +++ b/webapp_create_post.py @@ -177,7 +177,8 @@ def htmlNewPost(cssCache: {}, mediaInstance: bool, translate: {}, nickname: str, domain: str, domainFull: str, defaultTimeline: str, newswire: {}, - theme: str, noDropDown: bool) -> str: + theme: str, noDropDown: bool, + accessKeys: {}) -> str: """New post screen """ replyStr = '' @@ -579,7 +580,8 @@ def htmlNewPost(cssCache: {}, mediaInstance: bool, translate: {}, '
    \n' + \ '\n' + translate['Switch to timeline view'] + '" ' + \ + 'accesskey="' + accessKeys['menuTimeline'] + '">\n' newPostForm += '\n' + \ '
    \n' @@ -693,7 +695,8 @@ def htmlNewPost(cssCache: {}, mediaInstance: bool, translate: {}, newPostForm += \ '
    \n' + translate['Submit'] + '" ' + \ + 'accesskey="' + accessKeys['submitButton'] + '">\n' newPostForm += ' \n' newPostForm += '
    ' + '' keyStr += '
    \n' diff --git a/webapp_profile.py b/webapp_profile.py index b8eb9d984..446fd47f8 100644 --- a/webapp_profile.py +++ b/webapp_profile.py @@ -516,7 +516,7 @@ def htmlProfile(rssIconAtTop: bool, YTReplacementDomain, showPublishedDateOnly, newswire, theme, extraJson, - allowLocalNetworkAccess, + allowLocalNetworkAccess, accessKeys, pageNumber, maxItemsPerPage) domain, port = getDomainFromActor(profileJson['id']) diff --git a/webapp_timeline.py b/webapp_timeline.py index 2ee1a7ffd..85d3851bf 100644 --- a/webapp_timeline.py +++ b/webapp_timeline.py @@ -535,7 +535,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, getLeftColumnContent(baseDir, nickname, domainFull, httpPrefix, translate, editor, False, None, rssIconAtTop, - True, False, theme) + True, False, theme, accessKeys) tlStr += ' ' + \ leftColumnStr + '
    \n' From ce27c316e4c801ffce966a20a47c16011f6cf877 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 23 Apr 2021 18:23:12 +0100 Subject: [PATCH 44/54] Key shortcuts for new post dropdown --- daemon.py | 4 +++- webapp_create_post.py | 29 +++++++++++++++++++---------- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/daemon.py b/daemon.py index f506adac0..103faf1e9 100644 --- a/daemon.py +++ b/daemon.py @@ -14845,7 +14845,9 @@ def runDaemon(brochMode: bool, 'menuRoles': 'o', 'menuSkills': 'a', 'menuLogout': 'x', - 'menuKeys': 'k' + 'menuKeys': 'k', + 'Public': 'p', + 'Reminder': 'r' } httpd.keyShortcuts = {} loadAccessKeysForAccounts(baseDir, httpd.keyShortcuts) diff --git a/webapp_create_post.py b/webapp_create_post.py index 904bcca63..8d5d6a251 100644 --- a/webapp_create_post.py +++ b/webapp_create_post.py @@ -72,7 +72,8 @@ def _htmlNewPostDropDown(scopeIcon: str, scopeDescription: str, dropdownReminderSuffix: str, dropdownEventSuffix: str, dropdownReportSuffix: str, - noDropDown: bool) -> str: + noDropDown: bool, + accessKeys: {}) -> str: """Returns the html for a drop down list of new post types """ dropDownContent = '