mirror of https://gitlab.com/bashrc2/epicyon
Merge branch 'main' of ssh://code.freedombone.net:2222/bashrc/epicyon
commit
a17b72b63b
12
blog.py
12
blog.py
|
|
@ -619,7 +619,9 @@ def _noOfBlogAccounts(baseDir: str) -> int:
|
||||||
for acct in dirs:
|
for acct in dirs:
|
||||||
if '@' not in acct:
|
if '@' not in acct:
|
||||||
continue
|
continue
|
||||||
if 'inbox@' in acct:
|
if acct.startswith('inbox@'):
|
||||||
|
continue
|
||||||
|
elif acct.startswith('news@'):
|
||||||
continue
|
continue
|
||||||
accountDir = os.path.join(baseDir + '/accounts', acct)
|
accountDir = os.path.join(baseDir + '/accounts', acct)
|
||||||
blogsIndex = accountDir + '/tlblogs.index'
|
blogsIndex = accountDir + '/tlblogs.index'
|
||||||
|
|
@ -636,7 +638,9 @@ def _singleBlogAccountNickname(baseDir: str) -> str:
|
||||||
for acct in dirs:
|
for acct in dirs:
|
||||||
if '@' not in acct:
|
if '@' not in acct:
|
||||||
continue
|
continue
|
||||||
if 'inbox@' in acct:
|
if acct.startswith('inbox@'):
|
||||||
|
continue
|
||||||
|
elif acct.startswith('news@'):
|
||||||
continue
|
continue
|
||||||
accountDir = os.path.join(baseDir + '/accounts', acct)
|
accountDir = os.path.join(baseDir + '/accounts', acct)
|
||||||
blogsIndex = accountDir + '/tlblogs.index'
|
blogsIndex = accountDir + '/tlblogs.index'
|
||||||
|
|
@ -676,7 +680,9 @@ def htmlBlogView(authorized: bool,
|
||||||
for acct in dirs:
|
for acct in dirs:
|
||||||
if '@' not in acct:
|
if '@' not in acct:
|
||||||
continue
|
continue
|
||||||
if 'inbox@' in acct:
|
if acct.startswith('inbox@'):
|
||||||
|
continue
|
||||||
|
elif acct.startswith('news@'):
|
||||||
continue
|
continue
|
||||||
accountDir = os.path.join(baseDir + '/accounts', acct)
|
accountDir = os.path.join(baseDir + '/accounts', acct)
|
||||||
blogsIndex = accountDir + '/tlblogs.index'
|
blogsIndex = accountDir + '/tlblogs.index'
|
||||||
|
|
|
||||||
|
|
@ -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.
|
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 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.
|
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.
|
||||||
|
|
|
||||||
468
daemon.py
468
daemon.py
|
|
@ -134,6 +134,8 @@ from webapp_utils import getBlogAddress
|
||||||
from webapp_calendar import htmlCalendarDeleteConfirm
|
from webapp_calendar import htmlCalendarDeleteConfirm
|
||||||
from webapp_calendar import htmlCalendar
|
from webapp_calendar import htmlCalendar
|
||||||
from webapp_about import htmlAbout
|
from webapp_about import htmlAbout
|
||||||
|
from webapp_accesskeys import htmlAccessKeys
|
||||||
|
from webapp_accesskeys import loadAccessKeysForAccounts
|
||||||
from webapp_confirm import htmlConfirmDelete
|
from webapp_confirm import htmlConfirmDelete
|
||||||
from webapp_confirm import htmlConfirmRemoveSharedItem
|
from webapp_confirm import htmlConfirmRemoveSharedItem
|
||||||
from webapp_confirm import htmlConfirmUnblock
|
from webapp_confirm import htmlConfirmUnblock
|
||||||
|
|
@ -1800,6 +1802,93 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.POSTbusy = False
|
self.server.POSTbusy = False
|
||||||
return
|
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: {},
|
||||||
|
defaultTimeline: str) -> None:
|
||||||
|
"""Receive POST from webapp_accesskeys
|
||||||
|
"""
|
||||||
|
usersPath = '/users/' + nickname
|
||||||
|
originPathStr = \
|
||||||
|
httpPrefix + '://' + domainFull + usersPath + '/' + defaultTimeline
|
||||||
|
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 + '/' + defaultTimeline
|
||||||
|
elif callingDomain.endswith('.i2p') and i2pDomain:
|
||||||
|
originPathStr = \
|
||||||
|
'http://' + i2pDomain + usersPath + '/' + defaultTimeline
|
||||||
|
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 + '/' + defaultTimeline
|
||||||
|
elif callingDomain.endswith('.i2p') and i2pDomain:
|
||||||
|
originPathStr = \
|
||||||
|
'http://' + i2pDomain + usersPath + '/' + defaultTimeline
|
||||||
|
self._redirect_headers(originPathStr, cookie, callingDomain)
|
||||||
|
self.server.POSTbusy = False
|
||||||
|
return
|
||||||
|
|
||||||
def _personOptions(self, path: str,
|
def _personOptions(self, path: str,
|
||||||
callingDomain: str, cookie: str,
|
callingDomain: str, cookie: str,
|
||||||
baseDir: str, httpPrefix: str,
|
baseDir: str, httpPrefix: str,
|
||||||
|
|
@ -2168,6 +2257,15 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
if debug:
|
if debug:
|
||||||
print('Sending DM to ' + optionsActor)
|
print('Sending DM to ' + optionsActor)
|
||||||
reportPath = path.replace('/personoptions', '') + '/newdm'
|
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,
|
msg = htmlNewPost(self.server.cssCache,
|
||||||
False, self.server.translate,
|
False, self.server.translate,
|
||||||
baseDir,
|
baseDir,
|
||||||
|
|
@ -2181,7 +2279,7 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.defaultTimeline,
|
self.server.defaultTimeline,
|
||||||
self.server.newswire,
|
self.server.newswire,
|
||||||
self.server.themeName,
|
self.server.themeName,
|
||||||
True).encode('utf-8')
|
True, accessKeys).encode('utf-8')
|
||||||
msglen = len(msg)
|
msglen = len(msg)
|
||||||
self._set_headers('text/html', msglen,
|
self._set_headers('text/html', msglen,
|
||||||
cookie, callingDomain)
|
cookie, callingDomain)
|
||||||
|
|
@ -2268,6 +2366,15 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
print('Reporting ' + optionsActor)
|
print('Reporting ' + optionsActor)
|
||||||
reportPath = \
|
reportPath = \
|
||||||
path.replace('/personoptions', '') + '/newreport'
|
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,
|
msg = htmlNewPost(self.server.cssCache,
|
||||||
False, self.server.translate,
|
False, self.server.translate,
|
||||||
baseDir,
|
baseDir,
|
||||||
|
|
@ -2280,7 +2387,7 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.defaultTimeline,
|
self.server.defaultTimeline,
|
||||||
self.server.newswire,
|
self.server.newswire,
|
||||||
self.server.themeName,
|
self.server.themeName,
|
||||||
True).encode('utf-8')
|
True, accessKeys).encode('utf-8')
|
||||||
msglen = len(msg)
|
msglen = len(msg)
|
||||||
self._set_headers('text/html', msglen,
|
self._set_headers('text/html', msglen,
|
||||||
cookie, callingDomain)
|
cookie, callingDomain)
|
||||||
|
|
@ -2843,6 +2950,11 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
showPublishedDateOnly = self.server.showPublishedDateOnly
|
showPublishedDateOnly = self.server.showPublishedDateOnly
|
||||||
allowLocalNetworkAccess = \
|
allowLocalNetworkAccess = \
|
||||||
self.server.allowLocalNetworkAccess
|
self.server.allowLocalNetworkAccess
|
||||||
|
|
||||||
|
accessKeys = self.server.accessKeys
|
||||||
|
if self.server.keyShortcuts.get(nickname):
|
||||||
|
accessKeys = self.server.keyShortcuts[nickname]
|
||||||
|
|
||||||
profileStr = \
|
profileStr = \
|
||||||
htmlProfileAfterSearch(self.server.cssCache,
|
htmlProfileAfterSearch(self.server.cssCache,
|
||||||
self.server.recentPostsCache,
|
self.server.recentPostsCache,
|
||||||
|
|
@ -2865,7 +2977,8 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.defaultTimeline,
|
self.server.defaultTimeline,
|
||||||
self.server.peertubeInstances,
|
self.server.peertubeInstances,
|
||||||
allowLocalNetworkAccess,
|
allowLocalNetworkAccess,
|
||||||
self.server.themeName)
|
self.server.themeName,
|
||||||
|
accessKeys)
|
||||||
if profileStr:
|
if profileStr:
|
||||||
msg = profileStr.encode('utf-8')
|
msg = profileStr.encode('utf-8')
|
||||||
msglen = len(msg)
|
msglen = len(msg)
|
||||||
|
|
@ -5019,11 +5132,24 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
if os.path.isfile(blockedFilename):
|
if os.path.isfile(blockedFilename):
|
||||||
os.remove(blockedFilename)
|
os.remove(blockedFilename)
|
||||||
|
|
||||||
|
# Save DM allowed instances list.
|
||||||
|
# The allow list for incoming DMs,
|
||||||
|
# if the .followDMs flag file exists
|
||||||
|
dmAllowedInstancesFilename = \
|
||||||
|
baseDir + '/accounts/' + \
|
||||||
|
nickname + '@' + domain + '/dmAllowedinstances.txt'
|
||||||
|
if fields.get('dmAllowedInstances'):
|
||||||
|
with open(dmAllowedInstancesFilename, 'w+') as aFile:
|
||||||
|
aFile.write(fields['dmAllowedInstances'])
|
||||||
|
else:
|
||||||
|
if os.path.isfile(dmAllowedInstancesFilename):
|
||||||
|
os.remove(dmAllowedInstancesFilename)
|
||||||
|
|
||||||
# save allowed instances list
|
# save allowed instances list
|
||||||
|
# This is the account level allow list
|
||||||
allowedInstancesFilename = \
|
allowedInstancesFilename = \
|
||||||
baseDir + '/accounts/' + \
|
baseDir + '/accounts/' + \
|
||||||
nickname + '@' + domain + \
|
nickname + '@' + domain + '/allowedinstances.txt'
|
||||||
'/allowedinstances.txt'
|
|
||||||
if fields.get('allowedInstances'):
|
if fields.get('allowedInstances'):
|
||||||
with open(allowedInstancesFilename, 'w+') as aFile:
|
with open(allowedInstancesFilename, 'w+') as aFile:
|
||||||
aFile.write(fields['allowedInstances'])
|
aFile.write(fields['allowedInstances'])
|
||||||
|
|
@ -5703,6 +5829,13 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
optionsActor, optionsProfileUrl,
|
optionsActor, optionsProfileUrl,
|
||||||
self.server.personCache, 5)
|
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,
|
msg = htmlPersonOptions(self.server.defaultTimeline,
|
||||||
self.server.cssCache,
|
self.server.cssCache,
|
||||||
self.server.translate,
|
self.server.translate,
|
||||||
|
|
@ -5725,7 +5858,8 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
movedTo, alsoKnownAs,
|
movedTo, alsoKnownAs,
|
||||||
self.server.textModeBanner,
|
self.server.textModeBanner,
|
||||||
self.server.newsInstance,
|
self.server.newsInstance,
|
||||||
authorized).encode('utf-8')
|
authorized,
|
||||||
|
accessKeys).encode('utf-8')
|
||||||
msglen = len(msg)
|
msglen = len(msg)
|
||||||
self._set_headers('text/html', msglen,
|
self._set_headers('text/html', msglen,
|
||||||
cookie, callingDomain)
|
cookie, callingDomain)
|
||||||
|
|
@ -7329,6 +7463,11 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.YTReplacementDomain
|
self.server.YTReplacementDomain
|
||||||
iconsAsButtons = \
|
iconsAsButtons = \
|
||||||
self.server.iconsAsButtons
|
self.server.iconsAsButtons
|
||||||
|
|
||||||
|
accessKeys = self.server.accessKeys
|
||||||
|
if self.server.keyShortcuts.get(nickname):
|
||||||
|
accessKeys = self.server.keyShortcuts[nickname]
|
||||||
|
|
||||||
msg = \
|
msg = \
|
||||||
htmlProfile(self.server.rssIconAtTop,
|
htmlProfile(self.server.rssIconAtTop,
|
||||||
self.server.cssCache,
|
self.server.cssCache,
|
||||||
|
|
@ -7352,6 +7491,7 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.allowLocalNetworkAccess,
|
self.server.allowLocalNetworkAccess,
|
||||||
self.server.textModeBanner,
|
self.server.textModeBanner,
|
||||||
self.server.debug,
|
self.server.debug,
|
||||||
|
accessKeys,
|
||||||
actorJson['roles'],
|
actorJson['roles'],
|
||||||
None, None)
|
None, None)
|
||||||
msg = msg.encode('utf-8')
|
msg = msg.encode('utf-8')
|
||||||
|
|
@ -7418,6 +7558,10 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.iconsAsButtons
|
self.server.iconsAsButtons
|
||||||
allowLocalNetworkAccess = \
|
allowLocalNetworkAccess = \
|
||||||
self.server.allowLocalNetworkAccess
|
self.server.allowLocalNetworkAccess
|
||||||
|
accessKeys = self.server.accessKeys
|
||||||
|
if self.server.keyShortcuts.get(nickname):
|
||||||
|
accessKeys = \
|
||||||
|
self.server.keyShortcuts[nickname]
|
||||||
msg = \
|
msg = \
|
||||||
htmlProfile(self.server.rssIconAtTop,
|
htmlProfile(self.server.rssIconAtTop,
|
||||||
self.server.cssCache,
|
self.server.cssCache,
|
||||||
|
|
@ -7441,6 +7585,7 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
allowLocalNetworkAccess,
|
allowLocalNetworkAccess,
|
||||||
self.server.textModeBanner,
|
self.server.textModeBanner,
|
||||||
self.server.debug,
|
self.server.debug,
|
||||||
|
accessKeys,
|
||||||
actorJson['skills'],
|
actorJson['skills'],
|
||||||
None, None)
|
None, None)
|
||||||
msg = msg.encode('utf-8')
|
msg = msg.encode('utf-8')
|
||||||
|
|
@ -7808,6 +7953,12 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
fullWidthTimelineButtonHeader = \
|
fullWidthTimelineButtonHeader = \
|
||||||
self.server.fullWidthTimelineButtonHeader
|
self.server.fullWidthTimelineButtonHeader
|
||||||
minimalNick = self._isMinimal(nickname)
|
minimalNick = self._isMinimal(nickname)
|
||||||
|
|
||||||
|
accessKeys = self.server.accessKeys
|
||||||
|
if self.server.keyShortcuts.get(nickname):
|
||||||
|
accessKeys = \
|
||||||
|
self.server.keyShortcuts[nickname]
|
||||||
|
|
||||||
msg = htmlInbox(self.server.cssCache,
|
msg = htmlInbox(self.server.cssCache,
|
||||||
defaultTimeline,
|
defaultTimeline,
|
||||||
recentPostsCache,
|
recentPostsCache,
|
||||||
|
|
@ -7839,7 +7990,8 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.themeName,
|
self.server.themeName,
|
||||||
self.server.peertubeInstances,
|
self.server.peertubeInstances,
|
||||||
self.server.allowLocalNetworkAccess,
|
self.server.allowLocalNetworkAccess,
|
||||||
self.server.textModeBanner)
|
self.server.textModeBanner,
|
||||||
|
accessKeys)
|
||||||
if GETstartTime:
|
if GETstartTime:
|
||||||
self._benchmarkGETtimings(GETstartTime, GETtimings,
|
self._benchmarkGETtimings(GETstartTime, GETtimings,
|
||||||
'show status done',
|
'show status done',
|
||||||
|
|
@ -7937,6 +8089,12 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
fullWidthTimelineButtonHeader = \
|
fullWidthTimelineButtonHeader = \
|
||||||
self.server.fullWidthTimelineButtonHeader
|
self.server.fullWidthTimelineButtonHeader
|
||||||
minimalNick = self._isMinimal(nickname)
|
minimalNick = self._isMinimal(nickname)
|
||||||
|
|
||||||
|
accessKeys = self.server.accessKeys
|
||||||
|
if self.server.keyShortcuts.get(nickname):
|
||||||
|
accessKeys = \
|
||||||
|
self.server.keyShortcuts[nickname]
|
||||||
|
|
||||||
msg = \
|
msg = \
|
||||||
htmlInboxDMs(self.server.cssCache,
|
htmlInboxDMs(self.server.cssCache,
|
||||||
self.server.defaultTimeline,
|
self.server.defaultTimeline,
|
||||||
|
|
@ -7968,7 +8126,8 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
authorized, self.server.themeName,
|
authorized, self.server.themeName,
|
||||||
self.server.peertubeInstances,
|
self.server.peertubeInstances,
|
||||||
self.server.allowLocalNetworkAccess,
|
self.server.allowLocalNetworkAccess,
|
||||||
self.server.textModeBanner)
|
self.server.textModeBanner,
|
||||||
|
accessKeys)
|
||||||
msg = msg.encode('utf-8')
|
msg = msg.encode('utf-8')
|
||||||
msglen = len(msg)
|
msglen = len(msg)
|
||||||
self._set_headers('text/html', msglen,
|
self._set_headers('text/html', msglen,
|
||||||
|
|
@ -8059,6 +8218,12 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
fullWidthTimelineButtonHeader = \
|
fullWidthTimelineButtonHeader = \
|
||||||
self.server.fullWidthTimelineButtonHeader
|
self.server.fullWidthTimelineButtonHeader
|
||||||
minimalNick = self._isMinimal(nickname)
|
minimalNick = self._isMinimal(nickname)
|
||||||
|
|
||||||
|
accessKeys = self.server.accessKeys
|
||||||
|
if self.server.keyShortcuts.get(nickname):
|
||||||
|
accessKeys = \
|
||||||
|
self.server.keyShortcuts[nickname]
|
||||||
|
|
||||||
msg = \
|
msg = \
|
||||||
htmlInboxReplies(self.server.cssCache,
|
htmlInboxReplies(self.server.cssCache,
|
||||||
self.server.defaultTimeline,
|
self.server.defaultTimeline,
|
||||||
|
|
@ -8090,7 +8255,8 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
authorized, self.server.themeName,
|
authorized, self.server.themeName,
|
||||||
self.server.peertubeInstances,
|
self.server.peertubeInstances,
|
||||||
self.server.allowLocalNetworkAccess,
|
self.server.allowLocalNetworkAccess,
|
||||||
self.server.textModeBanner)
|
self.server.textModeBanner,
|
||||||
|
accessKeys)
|
||||||
msg = msg.encode('utf-8')
|
msg = msg.encode('utf-8')
|
||||||
msglen = len(msg)
|
msglen = len(msg)
|
||||||
self._set_headers('text/html', msglen,
|
self._set_headers('text/html', msglen,
|
||||||
|
|
@ -8181,6 +8347,12 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
fullWidthTimelineButtonHeader = \
|
fullWidthTimelineButtonHeader = \
|
||||||
self.server.fullWidthTimelineButtonHeader
|
self.server.fullWidthTimelineButtonHeader
|
||||||
minimalNick = self._isMinimal(nickname)
|
minimalNick = self._isMinimal(nickname)
|
||||||
|
|
||||||
|
accessKeys = self.server.accessKeys
|
||||||
|
if self.server.keyShortcuts.get(nickname):
|
||||||
|
accessKeys = \
|
||||||
|
self.server.keyShortcuts[nickname]
|
||||||
|
|
||||||
msg = \
|
msg = \
|
||||||
htmlInboxMedia(self.server.cssCache,
|
htmlInboxMedia(self.server.cssCache,
|
||||||
self.server.defaultTimeline,
|
self.server.defaultTimeline,
|
||||||
|
|
@ -8213,7 +8385,8 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.themeName,
|
self.server.themeName,
|
||||||
self.server.peertubeInstances,
|
self.server.peertubeInstances,
|
||||||
self.server.allowLocalNetworkAccess,
|
self.server.allowLocalNetworkAccess,
|
||||||
self.server.textModeBanner)
|
self.server.textModeBanner,
|
||||||
|
accessKeys)
|
||||||
msg = msg.encode('utf-8')
|
msg = msg.encode('utf-8')
|
||||||
msglen = len(msg)
|
msglen = len(msg)
|
||||||
self._set_headers('text/html', msglen,
|
self._set_headers('text/html', msglen,
|
||||||
|
|
@ -8304,6 +8477,12 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
fullWidthTimelineButtonHeader = \
|
fullWidthTimelineButtonHeader = \
|
||||||
self.server.fullWidthTimelineButtonHeader
|
self.server.fullWidthTimelineButtonHeader
|
||||||
minimalNick = self._isMinimal(nickname)
|
minimalNick = self._isMinimal(nickname)
|
||||||
|
|
||||||
|
accessKeys = self.server.accessKeys
|
||||||
|
if self.server.keyShortcuts.get(nickname):
|
||||||
|
accessKeys = \
|
||||||
|
self.server.keyShortcuts[nickname]
|
||||||
|
|
||||||
msg = \
|
msg = \
|
||||||
htmlInboxBlogs(self.server.cssCache,
|
htmlInboxBlogs(self.server.cssCache,
|
||||||
self.server.defaultTimeline,
|
self.server.defaultTimeline,
|
||||||
|
|
@ -8336,7 +8515,8 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.themeName,
|
self.server.themeName,
|
||||||
self.server.peertubeInstances,
|
self.server.peertubeInstances,
|
||||||
self.server.allowLocalNetworkAccess,
|
self.server.allowLocalNetworkAccess,
|
||||||
self.server.textModeBanner)
|
self.server.textModeBanner,
|
||||||
|
accessKeys)
|
||||||
msg = msg.encode('utf-8')
|
msg = msg.encode('utf-8')
|
||||||
msglen = len(msg)
|
msglen = len(msg)
|
||||||
self._set_headers('text/html', msglen,
|
self._set_headers('text/html', msglen,
|
||||||
|
|
@ -8435,6 +8615,12 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
fullWidthTimelineButtonHeader = \
|
fullWidthTimelineButtonHeader = \
|
||||||
self.server.fullWidthTimelineButtonHeader
|
self.server.fullWidthTimelineButtonHeader
|
||||||
minimalNick = self._isMinimal(nickname)
|
minimalNick = self._isMinimal(nickname)
|
||||||
|
|
||||||
|
accessKeys = self.server.accessKeys
|
||||||
|
if self.server.keyShortcuts.get(nickname):
|
||||||
|
accessKeys = \
|
||||||
|
self.server.keyShortcuts[nickname]
|
||||||
|
|
||||||
msg = \
|
msg = \
|
||||||
htmlInboxNews(self.server.cssCache,
|
htmlInboxNews(self.server.cssCache,
|
||||||
self.server.defaultTimeline,
|
self.server.defaultTimeline,
|
||||||
|
|
@ -8468,7 +8654,8 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.themeName,
|
self.server.themeName,
|
||||||
self.server.peertubeInstances,
|
self.server.peertubeInstances,
|
||||||
self.server.allowLocalNetworkAccess,
|
self.server.allowLocalNetworkAccess,
|
||||||
self.server.textModeBanner)
|
self.server.textModeBanner,
|
||||||
|
accessKeys)
|
||||||
msg = msg.encode('utf-8')
|
msg = msg.encode('utf-8')
|
||||||
msglen = len(msg)
|
msglen = len(msg)
|
||||||
self._set_headers('text/html', msglen,
|
self._set_headers('text/html', msglen,
|
||||||
|
|
@ -8564,6 +8751,12 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
fullWidthTimelineButtonHeader = \
|
fullWidthTimelineButtonHeader = \
|
||||||
self.server.fullWidthTimelineButtonHeader
|
self.server.fullWidthTimelineButtonHeader
|
||||||
minimalNick = self._isMinimal(nickname)
|
minimalNick = self._isMinimal(nickname)
|
||||||
|
|
||||||
|
accessKeys = self.server.accessKeys
|
||||||
|
if self.server.keyShortcuts.get(nickname):
|
||||||
|
accessKeys = \
|
||||||
|
self.server.keyShortcuts[nickname]
|
||||||
|
|
||||||
msg = \
|
msg = \
|
||||||
htmlInboxFeatures(self.server.cssCache,
|
htmlInboxFeatures(self.server.cssCache,
|
||||||
self.server.defaultTimeline,
|
self.server.defaultTimeline,
|
||||||
|
|
@ -8596,7 +8789,8 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.themeName,
|
self.server.themeName,
|
||||||
self.server.peertubeInstances,
|
self.server.peertubeInstances,
|
||||||
self.server.allowLocalNetworkAccess,
|
self.server.allowLocalNetworkAccess,
|
||||||
self.server.textModeBanner)
|
self.server.textModeBanner,
|
||||||
|
accessKeys)
|
||||||
msg = msg.encode('utf-8')
|
msg = msg.encode('utf-8')
|
||||||
msglen = len(msg)
|
msglen = len(msg)
|
||||||
self._set_headers('text/html', msglen,
|
self._set_headers('text/html', msglen,
|
||||||
|
|
@ -8656,6 +8850,12 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
pageNumber = int(pageNumber)
|
pageNumber = int(pageNumber)
|
||||||
else:
|
else:
|
||||||
pageNumber = 1
|
pageNumber = 1
|
||||||
|
|
||||||
|
accessKeys = self.server.accessKeys
|
||||||
|
if self.server.keyShortcuts.get(nickname):
|
||||||
|
accessKeys = \
|
||||||
|
self.server.keyShortcuts[nickname]
|
||||||
|
|
||||||
msg = \
|
msg = \
|
||||||
htmlShares(self.server.cssCache,
|
htmlShares(self.server.cssCache,
|
||||||
self.server.defaultTimeline,
|
self.server.defaultTimeline,
|
||||||
|
|
@ -8685,7 +8885,8 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
authorized, self.server.themeName,
|
authorized, self.server.themeName,
|
||||||
self.server.peertubeInstances,
|
self.server.peertubeInstances,
|
||||||
self.server.allowLocalNetworkAccess,
|
self.server.allowLocalNetworkAccess,
|
||||||
self.server.textModeBanner)
|
self.server.textModeBanner,
|
||||||
|
accessKeys)
|
||||||
msg = msg.encode('utf-8')
|
msg = msg.encode('utf-8')
|
||||||
msglen = len(msg)
|
msglen = len(msg)
|
||||||
self._set_headers('text/html', msglen,
|
self._set_headers('text/html', msglen,
|
||||||
|
|
@ -8759,6 +8960,12 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
fullWidthTimelineButtonHeader = \
|
fullWidthTimelineButtonHeader = \
|
||||||
self.server.fullWidthTimelineButtonHeader
|
self.server.fullWidthTimelineButtonHeader
|
||||||
minimalNick = self._isMinimal(nickname)
|
minimalNick = self._isMinimal(nickname)
|
||||||
|
|
||||||
|
accessKeys = self.server.accessKeys
|
||||||
|
if self.server.keyShortcuts.get(nickname):
|
||||||
|
accessKeys = \
|
||||||
|
self.server.keyShortcuts[nickname]
|
||||||
|
|
||||||
msg = \
|
msg = \
|
||||||
htmlBookmarks(self.server.cssCache,
|
htmlBookmarks(self.server.cssCache,
|
||||||
self.server.defaultTimeline,
|
self.server.defaultTimeline,
|
||||||
|
|
@ -8791,7 +8998,8 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.themeName,
|
self.server.themeName,
|
||||||
self.server.peertubeInstances,
|
self.server.peertubeInstances,
|
||||||
self.server.allowLocalNetworkAccess,
|
self.server.allowLocalNetworkAccess,
|
||||||
self.server.textModeBanner)
|
self.server.textModeBanner,
|
||||||
|
accessKeys)
|
||||||
msg = msg.encode('utf-8')
|
msg = msg.encode('utf-8')
|
||||||
msglen = len(msg)
|
msglen = len(msg)
|
||||||
self._set_headers('text/html', msglen,
|
self._set_headers('text/html', msglen,
|
||||||
|
|
@ -8885,6 +9093,12 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
fullWidthTimelineButtonHeader = \
|
fullWidthTimelineButtonHeader = \
|
||||||
self.server.fullWidthTimelineButtonHeader
|
self.server.fullWidthTimelineButtonHeader
|
||||||
minimalNick = self._isMinimal(nickname)
|
minimalNick = self._isMinimal(nickname)
|
||||||
|
|
||||||
|
accessKeys = self.server.accessKeys
|
||||||
|
if self.server.keyShortcuts.get(nickname):
|
||||||
|
accessKeys = \
|
||||||
|
self.server.keyShortcuts[nickname]
|
||||||
|
|
||||||
msg = \
|
msg = \
|
||||||
htmlEvents(self.server.cssCache,
|
htmlEvents(self.server.cssCache,
|
||||||
self.server.defaultTimeline,
|
self.server.defaultTimeline,
|
||||||
|
|
@ -8917,7 +9131,8 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.themeName,
|
self.server.themeName,
|
||||||
self.server.peertubeInstances,
|
self.server.peertubeInstances,
|
||||||
self.server.allowLocalNetworkAccess,
|
self.server.allowLocalNetworkAccess,
|
||||||
self.server.textModeBanner)
|
self.server.textModeBanner,
|
||||||
|
accessKeys)
|
||||||
msg = msg.encode('utf-8')
|
msg = msg.encode('utf-8')
|
||||||
msglen = len(msg)
|
msglen = len(msg)
|
||||||
self._set_headers('text/html', msglen,
|
self._set_headers('text/html', msglen,
|
||||||
|
|
@ -9003,6 +9218,12 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
fullWidthTimelineButtonHeader = \
|
fullWidthTimelineButtonHeader = \
|
||||||
self.server.fullWidthTimelineButtonHeader
|
self.server.fullWidthTimelineButtonHeader
|
||||||
minimalNick = self._isMinimal(nickname)
|
minimalNick = self._isMinimal(nickname)
|
||||||
|
|
||||||
|
accessKeys = self.server.accessKeys
|
||||||
|
if self.server.keyShortcuts.get(nickname):
|
||||||
|
accessKeys = \
|
||||||
|
self.server.keyShortcuts[nickname]
|
||||||
|
|
||||||
msg = \
|
msg = \
|
||||||
htmlOutbox(self.server.cssCache,
|
htmlOutbox(self.server.cssCache,
|
||||||
self.server.defaultTimeline,
|
self.server.defaultTimeline,
|
||||||
|
|
@ -9035,7 +9256,8 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.themeName,
|
self.server.themeName,
|
||||||
self.server.peertubeInstances,
|
self.server.peertubeInstances,
|
||||||
self.server.allowLocalNetworkAccess,
|
self.server.allowLocalNetworkAccess,
|
||||||
self.server.textModeBanner)
|
self.server.textModeBanner,
|
||||||
|
accessKeys)
|
||||||
msg = msg.encode('utf-8')
|
msg = msg.encode('utf-8')
|
||||||
msglen = len(msg)
|
msglen = len(msg)
|
||||||
self._set_headers('text/html', msglen,
|
self._set_headers('text/html', msglen,
|
||||||
|
|
@ -9112,6 +9334,12 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
fullWidthTimelineButtonHeader = \
|
fullWidthTimelineButtonHeader = \
|
||||||
self.server.fullWidthTimelineButtonHeader
|
self.server.fullWidthTimelineButtonHeader
|
||||||
moderationActionStr = ''
|
moderationActionStr = ''
|
||||||
|
|
||||||
|
accessKeys = self.server.accessKeys
|
||||||
|
if self.server.keyShortcuts.get(nickname):
|
||||||
|
accessKeys = \
|
||||||
|
self.server.keyShortcuts[nickname]
|
||||||
|
|
||||||
msg = \
|
msg = \
|
||||||
htmlModeration(self.server.cssCache,
|
htmlModeration(self.server.cssCache,
|
||||||
self.server.defaultTimeline,
|
self.server.defaultTimeline,
|
||||||
|
|
@ -9143,7 +9371,8 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.themeName,
|
self.server.themeName,
|
||||||
self.server.peertubeInstances,
|
self.server.peertubeInstances,
|
||||||
self.server.allowLocalNetworkAccess,
|
self.server.allowLocalNetworkAccess,
|
||||||
self.server.textModeBanner)
|
self.server.textModeBanner,
|
||||||
|
accessKeys)
|
||||||
msg = msg.encode('utf-8')
|
msg = msg.encode('utf-8')
|
||||||
msglen = len(msg)
|
msglen = len(msg)
|
||||||
self._set_headers('text/html', msglen,
|
self._set_headers('text/html', msglen,
|
||||||
|
|
@ -9222,6 +9451,16 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self._404()
|
self._404()
|
||||||
self.server.GETbusy = False
|
self.server.GETbusy = False
|
||||||
return True
|
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 = \
|
msg = \
|
||||||
htmlProfile(self.server.rssIconAtTop,
|
htmlProfile(self.server.rssIconAtTop,
|
||||||
self.server.cssCache,
|
self.server.cssCache,
|
||||||
|
|
@ -9246,6 +9485,7 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.allowLocalNetworkAccess,
|
self.server.allowLocalNetworkAccess,
|
||||||
self.server.textModeBanner,
|
self.server.textModeBanner,
|
||||||
self.server.debug,
|
self.server.debug,
|
||||||
|
accessKeys,
|
||||||
shares,
|
shares,
|
||||||
pageNumber, sharesPerPage)
|
pageNumber, sharesPerPage)
|
||||||
msg = msg.encode('utf-8')
|
msg = msg.encode('utf-8')
|
||||||
|
|
@ -9322,6 +9562,15 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.GETbusy = False
|
self.server.GETbusy = False
|
||||||
return True
|
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 = \
|
msg = \
|
||||||
htmlProfile(self.server.rssIconAtTop,
|
htmlProfile(self.server.rssIconAtTop,
|
||||||
self.server.cssCache,
|
self.server.cssCache,
|
||||||
|
|
@ -9346,6 +9595,7 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.allowLocalNetworkAccess,
|
self.server.allowLocalNetworkAccess,
|
||||||
self.server.textModeBanner,
|
self.server.textModeBanner,
|
||||||
self.server.debug,
|
self.server.debug,
|
||||||
|
accessKeys,
|
||||||
following,
|
following,
|
||||||
pageNumber,
|
pageNumber,
|
||||||
followsPerPage).encode('utf-8')
|
followsPerPage).encode('utf-8')
|
||||||
|
|
@ -9420,6 +9670,16 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self._404()
|
self._404()
|
||||||
self.server.GETbusy = False
|
self.server.GETbusy = False
|
||||||
return True
|
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 = \
|
msg = \
|
||||||
htmlProfile(self.server.rssIconAtTop,
|
htmlProfile(self.server.rssIconAtTop,
|
||||||
self.server.cssCache,
|
self.server.cssCache,
|
||||||
|
|
@ -9445,6 +9705,7 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.allowLocalNetworkAccess,
|
self.server.allowLocalNetworkAccess,
|
||||||
self.server.textModeBanner,
|
self.server.textModeBanner,
|
||||||
self.server.debug,
|
self.server.debug,
|
||||||
|
accessKeys,
|
||||||
followers,
|
followers,
|
||||||
pageNumber,
|
pageNumber,
|
||||||
followsPerPage).encode('utf-8')
|
followsPerPage).encode('utf-8')
|
||||||
|
|
@ -9542,6 +9803,16 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self._404()
|
self._404()
|
||||||
self.server.GETbusy = False
|
self.server.GETbusy = False
|
||||||
return True
|
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 = \
|
msg = \
|
||||||
htmlProfile(self.server.rssIconAtTop,
|
htmlProfile(self.server.rssIconAtTop,
|
||||||
self.server.cssCache,
|
self.server.cssCache,
|
||||||
|
|
@ -9567,6 +9838,7 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.allowLocalNetworkAccess,
|
self.server.allowLocalNetworkAccess,
|
||||||
self.server.textModeBanner,
|
self.server.textModeBanner,
|
||||||
self.server.debug,
|
self.server.debug,
|
||||||
|
accessKeys,
|
||||||
None, None).encode('utf-8')
|
None, None).encode('utf-8')
|
||||||
msglen = len(msg)
|
msglen = len(msg)
|
||||||
self._set_headers('text/html', msglen,
|
self._set_headers('text/html', msglen,
|
||||||
|
|
@ -10091,6 +10363,11 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
break
|
break
|
||||||
if isNewPostEndpoint:
|
if isNewPostEndpoint:
|
||||||
nickname = getNicknameFromActor(path)
|
nickname = getNicknameFromActor(path)
|
||||||
|
|
||||||
|
accessKeys = self.server.accessKeys
|
||||||
|
if self.server.keyShortcuts.get(nickname):
|
||||||
|
accessKeys = self.server.keyShortcuts[nickname]
|
||||||
|
|
||||||
msg = htmlNewPost(self.server.cssCache,
|
msg = htmlNewPost(self.server.cssCache,
|
||||||
mediaInstance,
|
mediaInstance,
|
||||||
translate,
|
translate,
|
||||||
|
|
@ -10105,7 +10382,7 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.defaultTimeline,
|
self.server.defaultTimeline,
|
||||||
self.server.newswire,
|
self.server.newswire,
|
||||||
self.server.themeName,
|
self.server.themeName,
|
||||||
noDropDown).encode('utf-8')
|
noDropDown, accessKeys).encode('utf-8')
|
||||||
if not msg:
|
if not msg:
|
||||||
print('Error replying to ' + inReplyToUrl)
|
print('Error replying to ' + inReplyToUrl)
|
||||||
self._404()
|
self._404()
|
||||||
|
|
@ -10158,6 +10435,14 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
"""Show the links from the left column
|
"""Show the links from the left column
|
||||||
"""
|
"""
|
||||||
if '/users/' in path and path.endswith('/editlinks'):
|
if '/users/' in path and path.endswith('/editlinks'):
|
||||||
|
nickname = 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 = htmlEditLinks(self.server.cssCache,
|
msg = htmlEditLinks(self.server.cssCache,
|
||||||
translate,
|
translate,
|
||||||
baseDir,
|
baseDir,
|
||||||
|
|
@ -10165,7 +10450,7 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
port,
|
port,
|
||||||
httpPrefix,
|
httpPrefix,
|
||||||
self.server.defaultTimeline,
|
self.server.defaultTimeline,
|
||||||
theme).encode('utf-8')
|
theme, accessKeys).encode('utf-8')
|
||||||
if msg:
|
if msg:
|
||||||
msglen = len(msg)
|
msglen = len(msg)
|
||||||
self._set_headers('text/html', msglen,
|
self._set_headers('text/html', msglen,
|
||||||
|
|
@ -10184,6 +10469,14 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
"""Show the newswire from the right column
|
"""Show the newswire from the right column
|
||||||
"""
|
"""
|
||||||
if '/users/' in path and path.endswith('/editnewswire'):
|
if '/users/' in path and path.endswith('/editnewswire'):
|
||||||
|
nickname = 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 = htmlEditNewswire(self.server.cssCache,
|
msg = htmlEditNewswire(self.server.cssCache,
|
||||||
translate,
|
translate,
|
||||||
baseDir,
|
baseDir,
|
||||||
|
|
@ -10191,7 +10484,8 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
port,
|
port,
|
||||||
httpPrefix,
|
httpPrefix,
|
||||||
self.server.defaultTimeline,
|
self.server.defaultTimeline,
|
||||||
self.server.themeName).encode('utf-8')
|
self.server.themeName,
|
||||||
|
accessKeys).encode('utf-8')
|
||||||
if msg:
|
if msg:
|
||||||
msglen = len(msg)
|
msglen = len(msg)
|
||||||
self._set_headers('text/html', msglen,
|
self._set_headers('text/html', msglen,
|
||||||
|
|
@ -10984,6 +11278,34 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
'show about screen')
|
'show about screen')
|
||||||
return
|
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,
|
||||||
|
self.server.defaultTimeline)
|
||||||
|
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,
|
self._benchmarkGETtimings(GETstartTime, GETtimings,
|
||||||
'following accounts done',
|
'following accounts done',
|
||||||
'show about screen done')
|
'show about screen done')
|
||||||
|
|
@ -11465,6 +11787,9 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
rssIconAtTop = self.server.rssIconAtTop
|
rssIconAtTop = self.server.rssIconAtTop
|
||||||
iconsAsButtons = self.server.iconsAsButtons
|
iconsAsButtons = self.server.iconsAsButtons
|
||||||
defaultTimeline = self.server.defaultTimeline
|
defaultTimeline = self.server.defaultTimeline
|
||||||
|
accessKeys = self.server.accessKeys
|
||||||
|
if self.server.keyShortcuts.get(nickname):
|
||||||
|
accessKeys = self.server.keyShortcuts[nickname]
|
||||||
msg = htmlNewswireMobile(self.server.cssCache,
|
msg = htmlNewswireMobile(self.server.cssCache,
|
||||||
self.server.baseDir,
|
self.server.baseDir,
|
||||||
nickname,
|
nickname,
|
||||||
|
|
@ -11480,7 +11805,8 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
rssIconAtTop,
|
rssIconAtTop,
|
||||||
iconsAsButtons,
|
iconsAsButtons,
|
||||||
defaultTimeline,
|
defaultTimeline,
|
||||||
self.server.themeName).encode('utf-8')
|
self.server.themeName,
|
||||||
|
accessKeys).encode('utf-8')
|
||||||
msglen = len(msg)
|
msglen = len(msg)
|
||||||
self._set_headers('text/html', msglen,
|
self._set_headers('text/html', msglen,
|
||||||
cookie, callingDomain)
|
cookie, callingDomain)
|
||||||
|
|
@ -11499,6 +11825,9 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self._404()
|
self._404()
|
||||||
self.server.GETbusy = False
|
self.server.GETbusy = False
|
||||||
return
|
return
|
||||||
|
accessKeys = self.server.accessKeys
|
||||||
|
if self.server.keyShortcuts.get(nickname):
|
||||||
|
accessKeys = self.server.keyShortcuts[nickname]
|
||||||
timelinePath = \
|
timelinePath = \
|
||||||
'/users/' + nickname + '/' + self.server.defaultTimeline
|
'/users/' + nickname + '/' + self.server.defaultTimeline
|
||||||
iconsAsButtons = self.server.iconsAsButtons
|
iconsAsButtons = self.server.iconsAsButtons
|
||||||
|
|
@ -11513,7 +11842,8 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.rssIconAtTop,
|
self.server.rssIconAtTop,
|
||||||
iconsAsButtons,
|
iconsAsButtons,
|
||||||
defaultTimeline,
|
defaultTimeline,
|
||||||
self.server.themeName).encode('utf-8')
|
self.server.themeName,
|
||||||
|
accessKeys).encode('utf-8')
|
||||||
msglen = len(msg)
|
msglen = len(msg)
|
||||||
self._set_headers('text/html', msglen, cookie, callingDomain)
|
self._set_headers('text/html', msglen, cookie, callingDomain)
|
||||||
self._write(msg)
|
self._write(msg)
|
||||||
|
|
@ -11577,6 +11907,15 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
'/search?' in self.path:
|
'/search?' in self.path:
|
||||||
if '?' in self.path:
|
if '?' in self.path:
|
||||||
self.path = self.path.split('?')[0]
|
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
|
# show the search screen
|
||||||
msg = htmlSearch(self.server.cssCache,
|
msg = htmlSearch(self.server.cssCache,
|
||||||
self.server.translate,
|
self.server.translate,
|
||||||
|
|
@ -11584,7 +11923,8 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.domain,
|
self.server.domain,
|
||||||
self.server.defaultTimeline,
|
self.server.defaultTimeline,
|
||||||
self.server.themeName,
|
self.server.themeName,
|
||||||
self.server.textModeBanner).encode('utf-8')
|
self.server.textModeBanner,
|
||||||
|
accessKeys).encode('utf-8')
|
||||||
msglen = len(msg)
|
msglen = len(msg)
|
||||||
self._set_headers('text/html', msglen, cookie, callingDomain)
|
self._set_headers('text/html', msglen, cookie, callingDomain)
|
||||||
self._write(msg)
|
self._write(msg)
|
||||||
|
|
@ -11619,6 +11959,14 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
# Show the calendar for a user
|
# Show the calendar for a user
|
||||||
if htmlGET and usersInPath:
|
if htmlGET and usersInPath:
|
||||||
if '/calendar' in self.path:
|
if '/calendar' in self.path:
|
||||||
|
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 calendar screen
|
# show the calendar screen
|
||||||
msg = htmlCalendar(self.server.personCache,
|
msg = htmlCalendar(self.server.personCache,
|
||||||
self.server.cssCache,
|
self.server.cssCache,
|
||||||
|
|
@ -11626,7 +11974,8 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.baseDir, self.path,
|
self.server.baseDir, self.path,
|
||||||
self.server.httpPrefix,
|
self.server.httpPrefix,
|
||||||
self.server.domainFull,
|
self.server.domainFull,
|
||||||
self.server.textModeBanner).encode('utf-8')
|
self.server.textModeBanner,
|
||||||
|
accessKeys).encode('utf-8')
|
||||||
msglen = len(msg)
|
msglen = len(msg)
|
||||||
self._set_headers('text/html', msglen, cookie, callingDomain)
|
self._set_headers('text/html', msglen, cookie, callingDomain)
|
||||||
self._write(msg)
|
self._write(msg)
|
||||||
|
|
@ -13987,6 +14336,33 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.debug)
|
self.server.debug)
|
||||||
return
|
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]
|
||||||
|
|
||||||
|
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,
|
||||||
|
self.server.httpPrefix,
|
||||||
|
nickname,
|
||||||
|
self.server.domain,
|
||||||
|
self.server.domainFull,
|
||||||
|
self.server.port,
|
||||||
|
self.server.onionDomain,
|
||||||
|
self.server.i2pDomain,
|
||||||
|
self.server.debug,
|
||||||
|
accessKeys,
|
||||||
|
self.server.defaultTimeline)
|
||||||
|
return
|
||||||
|
|
||||||
self._benchmarkPOSTtimings(POSTstartTime, POSTtimings, 14)
|
self._benchmarkPOSTtimings(POSTstartTime, POSTtimings, 14)
|
||||||
|
|
||||||
# receive different types of post created by htmlNewPost
|
# receive different types of post created by htmlNewPost
|
||||||
|
|
@ -14464,6 +14840,48 @@ def runDaemon(brochMode: bool,
|
||||||
# ASCII/ANSI text banner used in shell browsers, such as Lynx
|
# ASCII/ANSI text banner used in shell browsers, such as Lynx
|
||||||
httpd.textModeBanner = getTextModeBanner(baseDir)
|
httpd.textModeBanner = getTextModeBanner(baseDir)
|
||||||
|
|
||||||
|
# key shortcuts SHIFT + ALT + [key]
|
||||||
|
httpd.accessKeys = {
|
||||||
|
'Page up': ',',
|
||||||
|
'Page down': '.',
|
||||||
|
'submitButton': 'y',
|
||||||
|
'followButton': 'f',
|
||||||
|
'blockButton': 'b',
|
||||||
|
'infoButton': 'i',
|
||||||
|
'snoozeButton': 's',
|
||||||
|
'reportButton': '[',
|
||||||
|
'viewButton': 'v',
|
||||||
|
'enterPetname': 'p',
|
||||||
|
'enterNotes': 'n',
|
||||||
|
'menuTimeline': 't',
|
||||||
|
'menuEdit': 'e',
|
||||||
|
'menuProfile': 'p',
|
||||||
|
'menuInbox': 'i',
|
||||||
|
'menuSearch': '/',
|
||||||
|
'menuNewPost': 'n',
|
||||||
|
'menuCalendar': 'c',
|
||||||
|
'menuDM': 'd',
|
||||||
|
'menuReplies': 'r',
|
||||||
|
'menuOutbox': 's',
|
||||||
|
'menuBookmarks': 'q',
|
||||||
|
'menuShares': 'h',
|
||||||
|
'menuBlogs': 'b',
|
||||||
|
'menuNewswire': 'w',
|
||||||
|
'menuLinks': 'l',
|
||||||
|
'menuMedia': 'm',
|
||||||
|
'menuModeration': 'o',
|
||||||
|
'menuFollowing': 'f',
|
||||||
|
'menuFollowers': 'g',
|
||||||
|
'menuRoles': 'o',
|
||||||
|
'menuSkills': 'a',
|
||||||
|
'menuLogout': 'x',
|
||||||
|
'menuKeys': 'k',
|
||||||
|
'Public': 'p',
|
||||||
|
'Reminder': 'r'
|
||||||
|
}
|
||||||
|
httpd.keyShortcuts = {}
|
||||||
|
loadAccessKeysForAccounts(baseDir, httpd.keyShortcuts, httpd.accessKeys)
|
||||||
|
|
||||||
httpd.unitTest = unitTest
|
httpd.unitTest = unitTest
|
||||||
httpd.allowLocalNetworkAccess = allowLocalNetworkAccess
|
httpd.allowLocalNetworkAccess = allowLocalNetworkAccess
|
||||||
if unitTest:
|
if unitTest:
|
||||||
|
|
|
||||||
|
|
@ -197,6 +197,17 @@ figure {
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.accesskeys {
|
||||||
|
border: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.accesskeys-left {
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
.accesskeys-right {
|
||||||
|
width: 10%;
|
||||||
|
}
|
||||||
|
|
||||||
.cw {
|
.cw {
|
||||||
font-style: var(--cw-style);
|
font-style: var(--cw-style);
|
||||||
font-weight: var(--cw-weight);
|
font-weight: var(--cw-weight);
|
||||||
|
|
|
||||||
5
inbox.py
5
inbox.py
|
|
@ -11,6 +11,7 @@ import os
|
||||||
import datetime
|
import datetime
|
||||||
import time
|
import time
|
||||||
from linked_data_sig import verifyJsonSignature
|
from linked_data_sig import verifyJsonSignature
|
||||||
|
from utils import dmAllowedFromDomain
|
||||||
from utils import isRecentPost
|
from utils import isRecentPost
|
||||||
from utils import getConfigParam
|
from utils import getConfigParam
|
||||||
from utils import hasUsersPath
|
from utils import hasUsersPath
|
||||||
|
|
@ -2466,6 +2467,10 @@ def _inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int,
|
||||||
if not isFollowingActor(baseDir,
|
if not isFollowingActor(baseDir,
|
||||||
nickname, domain,
|
nickname, domain,
|
||||||
sendH):
|
sendH):
|
||||||
|
# DMs may always be allowed from some domains
|
||||||
|
if not dmAllowedFromDomain(baseDir,
|
||||||
|
nickname, domain,
|
||||||
|
sendingActorDomain):
|
||||||
# send back a bounce DM
|
# send back a bounce DM
|
||||||
if postJsonObject.get('id') and \
|
if postJsonObject.get('id') and \
|
||||||
postJsonObject.get('object'):
|
postJsonObject.get('object'):
|
||||||
|
|
|
||||||
4
theme.py
4
theme.py
|
|
@ -551,7 +551,9 @@ def _setThemeImages(baseDir: str, name: str) -> None:
|
||||||
for acct in dirs:
|
for acct in dirs:
|
||||||
if '@' not in acct:
|
if '@' not in acct:
|
||||||
continue
|
continue
|
||||||
if 'inbox@' in acct:
|
if acct.startswith('inbox@'):
|
||||||
|
continue
|
||||||
|
elif acct.startswith('news@'):
|
||||||
continue
|
continue
|
||||||
accountDir = \
|
accountDir = \
|
||||||
os.path.join(baseDir + '/accounts', acct)
|
os.path.join(baseDir + '/accounts', acct)
|
||||||
|
|
|
||||||
|
|
@ -401,5 +401,41 @@
|
||||||
"counselor": "مستشار",
|
"counselor": "مستشار",
|
||||||
"Counselors": "المستشارين",
|
"Counselors": "المستشارين",
|
||||||
"shocked": "صدمت",
|
"shocked": "صدمت",
|
||||||
"Encrypted": "مشفر"
|
"Encrypted": "مشفر",
|
||||||
|
"Direct Message permitted 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": "الاختصارات الرئيسية",
|
||||||
|
"submitButton": "زر الإرسال",
|
||||||
|
"menuMedia": "وسائط",
|
||||||
|
"followButton": "زر متابعة / متابعة",
|
||||||
|
"blockButton": "زر كتلة",
|
||||||
|
"infoButton": "زر المعلومات",
|
||||||
|
"snoozeButton": "زر الغفوة",
|
||||||
|
"reportButton": "زر تقرير",
|
||||||
|
"viewButton": "عرض زر",
|
||||||
|
"enterPetname": "أدخل PETNAME",
|
||||||
|
"enterNotes": "أدخل الملاحظات",
|
||||||
|
"These access keys may be used": "قد يتم استخدام مفاتيح الوصول هذه، عادة مع مفتاح ALT + SHIFT + مفتاح ALT +"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -401,5 +401,41 @@
|
||||||
"counselor": "conseller",
|
"counselor": "conseller",
|
||||||
"Counselors": "Consellers",
|
"Counselors": "Consellers",
|
||||||
"shocked": "sorprès",
|
"shocked": "sorprès",
|
||||||
"Encrypted": "Xifrat"
|
"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.",
|
||||||
|
"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",
|
||||||
|
"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",
|
||||||
|
"These access keys may be used": "Es poden utilitzar aquestes tecles d'accés, típicament amb Alt + Maj + tecla o Alt + clau"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -401,5 +401,41 @@
|
||||||
"counselor": "cynghorydd",
|
"counselor": "cynghorydd",
|
||||||
"Counselors": "Cynghorwyr",
|
"Counselors": "Cynghorwyr",
|
||||||
"shocked": "sioc",
|
"shocked": "sioc",
|
||||||
"Encrypted": "Amgryptio"
|
"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.",
|
||||||
|
"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",
|
||||||
|
"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",
|
||||||
|
"These access keys may be used": "Gellir defnyddio'r allweddi mynediad hyn, fel arfer gyda ALT + Shift + Allwedd Allwedd neu ALT +"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -401,5 +401,41 @@
|
||||||
"counselor": "Beraterin",
|
"counselor": "Beraterin",
|
||||||
"Counselors": "Berater",
|
"Counselors": "Berater",
|
||||||
"shocked": "schockiert",
|
"shocked": "schockiert",
|
||||||
"Encrypted": "Verschlüsselt"
|
"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.",
|
||||||
|
"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",
|
||||||
|
"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",
|
||||||
|
"These access keys may be used": "Diese Zugriffstasten können verwendet werden, typischerweise mit ALT + SHIFT + -Taste oder ALT + -Taste"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -401,5 +401,41 @@
|
||||||
"counselor": "counselor",
|
"counselor": "counselor",
|
||||||
"Counselors": "Counselors",
|
"Counselors": "Counselors",
|
||||||
"shocked": "shocked",
|
"shocked": "shocked",
|
||||||
"Encrypted": "Encrypted"
|
"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.",
|
||||||
|
"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",
|
||||||
|
"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",
|
||||||
|
"These access keys may be used": "These access keys may be used, typically with ALT + SHIFT + key or ALT + key"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -401,5 +401,41 @@
|
||||||
"counselor": "Consejera",
|
"counselor": "Consejera",
|
||||||
"Counselors": "Consejeras",
|
"Counselors": "Consejeras",
|
||||||
"shocked": "conmocionada",
|
"shocked": "conmocionada",
|
||||||
"Encrypted": "Cifrada"
|
"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.",
|
||||||
|
"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",
|
||||||
|
"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",
|
||||||
|
"These access keys may be used": "Se pueden usar estas teclas de acceso, típicamente con teclas ALT + MAYÚS + teclas o ALT +"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -401,5 +401,41 @@
|
||||||
"counselor": "Conseillère",
|
"counselor": "Conseillère",
|
||||||
"Counselors": "Conseillères",
|
"Counselors": "Conseillères",
|
||||||
"shocked": "sous le choc",
|
"shocked": "sous le choc",
|
||||||
"Encrypted": "Crypté"
|
"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.",
|
||||||
|
"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",
|
||||||
|
"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",
|
||||||
|
"These access keys may be used": "Ces touches d'accès peuvent être utilisées typiquement avec une touche Alt + Maj + ou Alt +"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -401,5 +401,41 @@
|
||||||
"counselor": "Comhairleoir",
|
"counselor": "Comhairleoir",
|
||||||
"Counselors": "Comhairleoirí",
|
"Counselors": "Comhairleoirí",
|
||||||
"shocked": "ionadh",
|
"shocked": "ionadh",
|
||||||
"Encrypted": "Criptithe"
|
"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.",
|
||||||
|
"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í",
|
||||||
|
"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",
|
||||||
|
"These access keys may be used": "Is féidir na heochracha rochtana seo a úsáid, de ghnáth le Alt + Shift + Eochair nó Alt + Eochair"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -401,5 +401,41 @@
|
||||||
"counselor": "काउंसलर",
|
"counselor": "काउंसलर",
|
||||||
"Counselors": "सलाहकार",
|
"Counselors": "सलाहकार",
|
||||||
"shocked": "हैरान",
|
"shocked": "हैरान",
|
||||||
"Encrypted": "को गोपित"
|
"Encrypted": "को गोपित",
|
||||||
|
"Direct Message permitted 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": "कुंजी शॉर्टकट",
|
||||||
|
"submitButton": "जमा करने वाला बटन",
|
||||||
|
"menuMedia": "मीडिया",
|
||||||
|
"followButton": "फॉलो / अनफ़ॉलो बटन",
|
||||||
|
"blockButton": "ब्लॉक बटन",
|
||||||
|
"infoButton": "जानकारी बटन",
|
||||||
|
"snoozeButton": "अलार्म को थोड़ी देर बंद करने वाला बटन",
|
||||||
|
"reportButton": "रिपोर्ट बटन",
|
||||||
|
"viewButton": "देखें बटन",
|
||||||
|
"enterPetname": "PETNAME दर्ज करें",
|
||||||
|
"enterNotes": "नोट्स दर्ज करें",
|
||||||
|
"These access keys may be used": "इन एक्सेस कुंजियों का उपयोग किया जा सकता है, आमतौर पर Alt + Shift + कुंजी या Alt + कुंजी के साथ"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -401,5 +401,41 @@
|
||||||
"counselor": "Consulente",
|
"counselor": "Consulente",
|
||||||
"Counselors": "Consiglieri",
|
"Counselors": "Consiglieri",
|
||||||
"shocked": "scioccata",
|
"shocked": "scioccata",
|
||||||
"Encrypted": "Crittografato"
|
"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.",
|
||||||
|
"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",
|
||||||
|
"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",
|
||||||
|
"These access keys may be used": "Questi tasti di accesso possono essere utilizzati, in genere con tasto ALT + MAIUSC + o ALT + Key"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -401,5 +401,41 @@
|
||||||
"counselor": "カウンセラー",
|
"counselor": "カウンセラー",
|
||||||
"Counselors": "カウンセラー",
|
"Counselors": "カウンセラー",
|
||||||
"shocked": "ショックを受けた",
|
"shocked": "ショックを受けた",
|
||||||
"Encrypted": "暗号化"
|
"Encrypted": "暗号化",
|
||||||
|
"Direct Message permitted 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": "キーショートカット",
|
||||||
|
"submitButton": "送信ボタン",
|
||||||
|
"menuMedia": "メディア",
|
||||||
|
"followButton": "フォロー/フォローダウンボタン",
|
||||||
|
"blockButton": "ブロックボタン",
|
||||||
|
"infoButton": "情報ボタン",
|
||||||
|
"snoozeButton": "スヌーズボタン",
|
||||||
|
"reportButton": "レポートボタン",
|
||||||
|
"viewButton": "ボタンを見る",
|
||||||
|
"enterPetname": "PetNameを入力してください",
|
||||||
|
"enterNotes": "ノートを入力してください",
|
||||||
|
"These access keys may be used": "これらのアクセスキーは、通常はAlt + Shift +キーまたはAlt +キーを使用して使用できます。"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -401,5 +401,41 @@
|
||||||
"counselor": "Pêşnîyarvan",
|
"counselor": "Pêşnîyarvan",
|
||||||
"Counselors": "Selêwirmendan",
|
"Counselors": "Selêwirmendan",
|
||||||
"shocked": "şok kirin",
|
"shocked": "şok kirin",
|
||||||
"Encrypted": "Encîfre 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.",
|
||||||
|
"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",
|
||||||
|
"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",
|
||||||
|
"These access keys may be used": "Dibe ku ev keysên gihîştinê bikar bînin, bi gelemperî bi alt + shift + key an alt + key"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -397,5 +397,41 @@
|
||||||
"counselor": "Counselors",
|
"counselor": "Counselors",
|
||||||
"Counselors": "Counselors",
|
"Counselors": "Counselors",
|
||||||
"shocked": "shocked",
|
"shocked": "shocked",
|
||||||
"Encrypted": "Encrypted"
|
"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.",
|
||||||
|
"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",
|
||||||
|
"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",
|
||||||
|
"These access keys may be used": "These access keys may be used, typically with ALT + SHIFT + key or ALT + key"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -401,5 +401,41 @@
|
||||||
"counselor": "Conselheira",
|
"counselor": "Conselheira",
|
||||||
"Counselors": "Conselheiras",
|
"Counselors": "Conselheiras",
|
||||||
"shocked": "chocada",
|
"shocked": "chocada",
|
||||||
"Encrypted": "Criptografada"
|
"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.",
|
||||||
|
"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",
|
||||||
|
"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",
|
||||||
|
"These access keys may be used": "Essas teclas de acesso podem ser usadas, normalmente com tecla Alt + Shift + Key ou Alt +"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -401,5 +401,41 @@
|
||||||
"counselor": "Советник",
|
"counselor": "Советник",
|
||||||
"Counselors": "Советники",
|
"Counselors": "Советники",
|
||||||
"shocked": "потрясенный",
|
"shocked": "потрясенный",
|
||||||
"Encrypted": "Зашифрованный"
|
"Encrypted": "Зашифрованный",
|
||||||
|
"Direct Message permitted 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": "Клавичные ярлыки",
|
||||||
|
"submitButton": "Отправить кнопку",
|
||||||
|
"menuMedia": "СМИ",
|
||||||
|
"followButton": "Следуйте / отписаться кнопка",
|
||||||
|
"blockButton": "Кнопка блокировки",
|
||||||
|
"infoButton": "Информация Кнопка",
|
||||||
|
"snoozeButton": "Кнопка сножения",
|
||||||
|
"reportButton": "Кнопка отчета",
|
||||||
|
"viewButton": "Кнопка просмотра",
|
||||||
|
"enterPetname": "Введите petname",
|
||||||
|
"enterNotes": "Введите ноты",
|
||||||
|
"These access keys may be used": "Эти ключевые ключи доступа могут быть использованы, обычно с ALT + Shift + Key или Alt + Key"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -401,5 +401,41 @@
|
||||||
"counselor": "顾问",
|
"counselor": "顾问",
|
||||||
"Counselors": "辅导员",
|
"Counselors": "辅导员",
|
||||||
"shocked": "震惊的",
|
"shocked": "震惊的",
|
||||||
"Encrypted": "加密的"
|
"Encrypted": "加密的",
|
||||||
|
"Direct Message permitted 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": "关键捷径",
|
||||||
|
"submitButton": "提交按钮",
|
||||||
|
"menuMedia": "媒体",
|
||||||
|
"followButton": "关注/取消关注按钮",
|
||||||
|
"blockButton": "块按钮",
|
||||||
|
"infoButton": "信息按钮",
|
||||||
|
"snoozeButton": "贪睡按钮",
|
||||||
|
"reportButton": "报告按钮",
|
||||||
|
"viewButton": "查看按钮",
|
||||||
|
"enterPetname": "进入宠物名",
|
||||||
|
"enterNotes": "输入笔记",
|
||||||
|
"These access keys may be used": "可以使用这些访问密钥,通常使用Alt + Shift +键或ALT +键"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
33
utils.py
33
utils.py
|
|
@ -388,7 +388,9 @@ def getFollowersOfPerson(baseDir: str,
|
||||||
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
|
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
|
||||||
for account in dirs:
|
for account in dirs:
|
||||||
filename = os.path.join(subdir, account) + '/' + followFile
|
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
|
continue
|
||||||
if not os.path.isfile(filename):
|
if not os.path.isfile(filename):
|
||||||
continue
|
continue
|
||||||
|
|
@ -1057,7 +1059,7 @@ def clearFromPostCaches(baseDir: str, recentPostsCache: {},
|
||||||
for acct in dirs:
|
for acct in dirs:
|
||||||
if '@' not in acct:
|
if '@' not in acct:
|
||||||
continue
|
continue
|
||||||
if 'inbox@' in acct:
|
if acct.startswith('inbox@'):
|
||||||
continue
|
continue
|
||||||
cacheDir = os.path.join(baseDir + '/accounts', acct)
|
cacheDir = os.path.join(baseDir + '/accounts', acct)
|
||||||
postFilename = cacheDir + filename
|
postFilename = cacheDir + filename
|
||||||
|
|
@ -1405,7 +1407,10 @@ def noOfAccounts(baseDir: str) -> bool:
|
||||||
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
|
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
|
||||||
for account in dirs:
|
for account in dirs:
|
||||||
if '@' in account:
|
if '@' in account:
|
||||||
if not account.startswith('inbox@'):
|
if account.startswith('inbox@'):
|
||||||
|
continue
|
||||||
|
elif account.startswith('news@'):
|
||||||
|
continue
|
||||||
accountCtr += 1
|
accountCtr += 1
|
||||||
break
|
break
|
||||||
return accountCtr
|
return accountCtr
|
||||||
|
|
@ -1420,7 +1425,8 @@ def noOfActiveAccountsMonthly(baseDir: str, months: int) -> bool:
|
||||||
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
|
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
|
||||||
for account in dirs:
|
for account in dirs:
|
||||||
if '@' in account:
|
if '@' in account:
|
||||||
if not account.startswith('inbox@'):
|
if not account.startswith('inbox@') and \
|
||||||
|
not account.startswith('news@'):
|
||||||
lastUsedFilename = \
|
lastUsedFilename = \
|
||||||
baseDir + '/accounts/' + account + '/.lastUsed'
|
baseDir + '/accounts/' + account + '/.lastUsed'
|
||||||
if os.path.isfile(lastUsedFilename):
|
if os.path.isfile(lastUsedFilename):
|
||||||
|
|
@ -2197,3 +2203,22 @@ def loadTranslationsFromFile(baseDir: str, language: str) -> ({}, str):
|
||||||
translationsFile = baseDir + '/translations/' + \
|
translationsFile = baseDir + '/translations/' + \
|
||||||
systemLanguage + '.json'
|
systemLanguage + '.json'
|
||||||
return loadJson(translationsFile), systemLanguage
|
return loadJson(translationsFile), systemLanguage
|
||||||
|
|
||||||
|
|
||||||
|
def dmAllowedFromDomain(baseDir: str,
|
||||||
|
nickname: str, domain: 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.
|
||||||
|
i.e. Mostly you only want DMs from followers, but there are
|
||||||
|
a few particular instances that you trust
|
||||||
|
"""
|
||||||
|
dmAllowedInstancesFilename = \
|
||||||
|
baseDir + '/accounts/' + \
|
||||||
|
nickname + '@' + domain + '/dmAllowedInstances.txt'
|
||||||
|
if not os.path.isfile(dmAllowedInstancesFilename):
|
||||||
|
return False
|
||||||
|
if sendingActorDomain + '\n' in open(dmAllowedInstancesFilename).read():
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,115 @@
|
||||||
|
__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: {},
|
||||||
|
accessKeysTemplate: {}) -> 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] = accessKeysTemplate.copy()
|
||||||
|
for variableName, key in accessKeysTemplate.items():
|
||||||
|
if accessKeys.get(variableName):
|
||||||
|
keyShortcuts[nickname][variableName] = \
|
||||||
|
accessKeys[variableName]
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
def htmlAccessKeys(cssCache: {}, baseDir: str,
|
||||||
|
nickname: str, domain: str,
|
||||||
|
translate: {}, accessKeys: {},
|
||||||
|
defaultAccessKeys: {},
|
||||||
|
defaultTimeline: str) -> 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 += '<div class="container">\n'
|
||||||
|
|
||||||
|
accessKeysForm += \
|
||||||
|
' <h1>' + translate['Key Shortcuts'] + '</h1>\n'
|
||||||
|
accessKeysForm += \
|
||||||
|
'<p>' + translate['These access keys may be used'] + \
|
||||||
|
'<label class="labels"></label></p>'
|
||||||
|
|
||||||
|
accessKeysForm += ' <form method="POST" action="' + \
|
||||||
|
'/users/' + nickname + '/changeAccessKeys">\n'
|
||||||
|
|
||||||
|
timelineKey = accessKeys['menuTimeline']
|
||||||
|
submitKey = accessKeys['submitButton']
|
||||||
|
accessKeysForm += \
|
||||||
|
' <center>\n' + \
|
||||||
|
' <button type="submit" class="button" ' + \
|
||||||
|
'name="submitAccessKeysCancel" accesskey="' + timelineKey + '">' + \
|
||||||
|
translate['Go Back'] + '</button>\n' + \
|
||||||
|
' <button type="submit" class="button" ' + \
|
||||||
|
'name="submitAccessKeys" accesskey="' + submitKey + '">' + \
|
||||||
|
translate['Submit'] + '</button>\n </center>\n'
|
||||||
|
|
||||||
|
accessKeysForm += ' <table class="accesskeys">\n'
|
||||||
|
accessKeysForm += ' <colgroup>\n'
|
||||||
|
accessKeysForm += ' <col span="1" class="accesskeys-left">\n'
|
||||||
|
accessKeysForm += ' <col span="1" class="accesskeys-center">\n'
|
||||||
|
accessKeysForm += ' </colgroup>\n'
|
||||||
|
accessKeysForm += ' <tbody>\n'
|
||||||
|
|
||||||
|
for variableName, key in defaultAccessKeys.items():
|
||||||
|
if not translate.get(variableName):
|
||||||
|
continue
|
||||||
|
keyStr = '<tr>'
|
||||||
|
keyStr += \
|
||||||
|
'<td><label class="labels">' + \
|
||||||
|
translate[variableName] + '</label></td>'
|
||||||
|
if accessKeys.get(variableName):
|
||||||
|
key = accessKeys[variableName]
|
||||||
|
if len(key) > 1:
|
||||||
|
key = key[0]
|
||||||
|
keyStr += \
|
||||||
|
'<td><input type="text" ' + \
|
||||||
|
'name="' + variableName.replace(' ', '_') + '" ' + \
|
||||||
|
'value="' + key + '">'
|
||||||
|
keyStr += '</td></tr>\n'
|
||||||
|
accessKeysForm += keyStr
|
||||||
|
|
||||||
|
accessKeysForm += ' </tbody>\n'
|
||||||
|
accessKeysForm += ' </table>\n'
|
||||||
|
accessKeysForm += ' </form>\n'
|
||||||
|
accessKeysForm += '</div>\n'
|
||||||
|
accessKeysForm += htmlFooter()
|
||||||
|
return accessKeysForm
|
||||||
|
|
@ -243,7 +243,7 @@ def _htmlCalendarDay(personCache: {}, cssCache: {}, translate: {},
|
||||||
def htmlCalendar(personCache: {}, cssCache: {}, translate: {},
|
def htmlCalendar(personCache: {}, cssCache: {}, translate: {},
|
||||||
baseDir: str, path: str,
|
baseDir: str, path: str,
|
||||||
httpPrefix: str, domainFull: str,
|
httpPrefix: str, domainFull: str,
|
||||||
textModeBanner: str) -> str:
|
textModeBanner: str, accessKeys: {}) -> str:
|
||||||
"""Show the calendar for a person
|
"""Show the calendar for a person
|
||||||
"""
|
"""
|
||||||
domain = domainFull
|
domain = domainFull
|
||||||
|
|
@ -348,17 +348,20 @@ def htmlCalendar(personCache: {}, cssCache: {}, translate: {},
|
||||||
calendarStr += '<caption class="calendar__banner--month">\n'
|
calendarStr += '<caption class="calendar__banner--month">\n'
|
||||||
calendarStr += \
|
calendarStr += \
|
||||||
' <a href="' + calActor + '/calendar?year=' + str(prevYear) + \
|
' <a href="' + calActor + '/calendar?year=' + str(prevYear) + \
|
||||||
'?month=' + str(prevMonthNumber) + '">'
|
'?month=' + str(prevMonthNumber) + '" ' + \
|
||||||
|
'accesskey="' + accessKeys['Page up'] + '">'
|
||||||
calendarStr += \
|
calendarStr += \
|
||||||
' <img loading="lazy" alt="' + translate['Previous month'] + \
|
' <img loading="lazy" alt="' + translate['Previous month'] + \
|
||||||
'" title="' + translate['Previous month'] + '" src="/icons' + \
|
'" title="' + translate['Previous month'] + '" src="/icons' + \
|
||||||
'/prev.png" class="buttonprev"/></a>\n'
|
'/prev.png" class="buttonprev"/></a>\n'
|
||||||
calendarStr += ' <a href="' + calActor + '/inbox" title="'
|
calendarStr += ' <a href="' + calActor + '/inbox" title="'
|
||||||
calendarStr += translate['Switch to timeline view'] + '">'
|
calendarStr += translate['Switch to timeline view'] + '" ' + \
|
||||||
|
'accesskey="' + accessKeys['menuTimeline'] + '">'
|
||||||
calendarStr += ' <h1>' + monthName + '</h1></a>\n'
|
calendarStr += ' <h1>' + monthName + '</h1></a>\n'
|
||||||
calendarStr += \
|
calendarStr += \
|
||||||
' <a href="' + calActor + '/calendar?year=' + str(nextYear) + \
|
' <a href="' + calActor + '/calendar?year=' + str(nextYear) + \
|
||||||
'?month=' + str(nextMonthNumber) + '">'
|
'?month=' + str(nextMonthNumber) + '" ' + \
|
||||||
|
'accesskey="' + accessKeys['Page down'] + '">'
|
||||||
calendarStr += \
|
calendarStr += \
|
||||||
' <img loading="lazy" alt="' + translate['Next month'] + \
|
' <img loading="lazy" alt="' + translate['Next month'] + \
|
||||||
'" title="' + translate['Next month'] + '" src="/icons' + \
|
'" title="' + translate['Next month'] + '" src="/icons' + \
|
||||||
|
|
@ -456,7 +459,11 @@ def htmlCalendar(personCache: {}, cssCache: {}, translate: {},
|
||||||
htmlHideFromScreenReader('←') + ' ' + translate['Previous month']
|
htmlHideFromScreenReader('←') + ' ' + translate['Previous month']
|
||||||
navLinks[prevMonthStr] = calActor + '/calendar?year=' + str(prevYear) + \
|
navLinks[prevMonthStr] = calActor + '/calendar?year=' + str(prevYear) + \
|
||||||
'?month=' + str(prevMonthNumber)
|
'?month=' + str(prevMonthNumber)
|
||||||
|
# TODO
|
||||||
|
navAccessKeys = {
|
||||||
|
}
|
||||||
screenReaderCal = \
|
screenReaderCal = \
|
||||||
htmlKeyboardNavigation(textModeBanner, navLinks, monthName)
|
htmlKeyboardNavigation(textModeBanner, navLinks, navAccessKeys,
|
||||||
|
monthName)
|
||||||
|
|
||||||
return headerStr + screenReaderCal + calendarStr + htmlFooter()
|
return headerStr + screenReaderCal + calendarStr + htmlFooter()
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,8 @@ def getLeftColumnContent(baseDir: str, nickname: str, domainFull: str,
|
||||||
editor: bool,
|
editor: bool,
|
||||||
showBackButton: bool, timelinePath: str,
|
showBackButton: bool, timelinePath: str,
|
||||||
rssIconAtTop: bool, showHeaderImage: bool,
|
rssIconAtTop: bool, showHeaderImage: bool,
|
||||||
frontPage: bool, theme: str) -> str:
|
frontPage: bool, theme: str,
|
||||||
|
accessKeys: {}) -> str:
|
||||||
"""Returns html content for the left column
|
"""Returns html content for the left column
|
||||||
"""
|
"""
|
||||||
htmlStr = ''
|
htmlStr = ''
|
||||||
|
|
@ -112,7 +113,8 @@ def getLeftColumnContent(baseDir: str, nickname: str, domainFull: str,
|
||||||
# show the edit icon
|
# show the edit icon
|
||||||
htmlStr += \
|
htmlStr += \
|
||||||
' <a href="' + \
|
' <a href="' + \
|
||||||
'/users/' + nickname + '/editlinks">' + \
|
'/users/' + nickname + '/editlinks" ' + \
|
||||||
|
'accesskey="' + accessKeys['menuEdit'] + '">' + \
|
||||||
'<img class="' + editImageClass + \
|
'<img class="' + editImageClass + \
|
||||||
'" loading="lazy" alt="' + \
|
'" loading="lazy" alt="' + \
|
||||||
translate['Edit Links'] + ' | " title="' + \
|
translate['Edit Links'] + ' | " title="' + \
|
||||||
|
|
@ -254,6 +256,11 @@ def getLeftColumnContent(baseDir: str, nickname: str, domainFull: str,
|
||||||
|
|
||||||
if firstSeparatorAdded:
|
if firstSeparatorAdded:
|
||||||
htmlStr += separatorStr
|
htmlStr += separatorStr
|
||||||
|
htmlStr += \
|
||||||
|
'<p class="login-text"><a href="/users/' + \
|
||||||
|
nickname + '/accesskeys" accesskey="' + \
|
||||||
|
accessKeys['menuKeys'] + '">' + \
|
||||||
|
translate['Key Shortcuts'] + '</a></p>'
|
||||||
htmlStr += \
|
htmlStr += \
|
||||||
'<p class="login-text"><a href="/about">' + \
|
'<p class="login-text"><a href="/about">' + \
|
||||||
translate['About this Instance'] + '</a></p>'
|
translate['About this Instance'] + '</a></p>'
|
||||||
|
|
@ -274,7 +281,7 @@ def htmlLinksMobile(cssCache: {}, baseDir: str,
|
||||||
rssIconAtTop: bool,
|
rssIconAtTop: bool,
|
||||||
iconsAsButtons: bool,
|
iconsAsButtons: bool,
|
||||||
defaultTimeline: str,
|
defaultTimeline: str,
|
||||||
theme: str) -> str:
|
theme: str, accessKeys: {}) -> str:
|
||||||
"""Show the left column links within mobile view
|
"""Show the left column links within mobile view
|
||||||
"""
|
"""
|
||||||
htmlStr = ''
|
htmlStr = ''
|
||||||
|
|
@ -300,7 +307,8 @@ def htmlLinksMobile(cssCache: {}, baseDir: str,
|
||||||
bannerFile, bannerFilename = \
|
bannerFile, bannerFilename = \
|
||||||
getBannerFile(baseDir, nickname, domain, theme)
|
getBannerFile(baseDir, nickname, domain, theme)
|
||||||
htmlStr += \
|
htmlStr += \
|
||||||
'<a href="/users/' + nickname + '/' + defaultTimeline + '">' + \
|
'<a href="/users/' + nickname + '/' + defaultTimeline + '" ' + \
|
||||||
|
'accesskey="' + accessKeys['menuTimeline'] + '">' + \
|
||||||
'<img loading="lazy" class="timeline-banner" ' + \
|
'<img loading="lazy" class="timeline-banner" ' + \
|
||||||
'alt="' + translate['Switch to timeline view'] + '" ' + \
|
'alt="' + translate['Switch to timeline view'] + '" ' + \
|
||||||
'src="/users/' + nickname + '/' + bannerFile + '" /></a>\n'
|
'src="/users/' + nickname + '/' + bannerFile + '" /></a>\n'
|
||||||
|
|
@ -317,7 +325,7 @@ def htmlLinksMobile(cssCache: {}, baseDir: str,
|
||||||
editor,
|
editor,
|
||||||
False, timelinePath,
|
False, timelinePath,
|
||||||
rssIconAtTop, False, False,
|
rssIconAtTop, False, False,
|
||||||
theme)
|
theme, accessKeys)
|
||||||
else:
|
else:
|
||||||
if editor:
|
if editor:
|
||||||
htmlStr += '<br><br><br>\n'
|
htmlStr += '<br><br><br>\n'
|
||||||
|
|
@ -334,7 +342,8 @@ def htmlLinksMobile(cssCache: {}, baseDir: str,
|
||||||
|
|
||||||
def htmlEditLinks(cssCache: {}, translate: {}, baseDir: str, path: str,
|
def htmlEditLinks(cssCache: {}, translate: {}, baseDir: str, path: str,
|
||||||
domain: str, port: int, httpPrefix: str,
|
domain: str, port: int, httpPrefix: str,
|
||||||
defaultTimeline: str, theme: str) -> str:
|
defaultTimeline: str, theme: str,
|
||||||
|
accessKeys: {}) -> str:
|
||||||
"""Shows the edit links screen
|
"""Shows the edit links screen
|
||||||
"""
|
"""
|
||||||
if '/users/' not in path:
|
if '/users/' not in path:
|
||||||
|
|
@ -367,7 +376,8 @@ def htmlEditLinks(cssCache: {}, translate: {}, baseDir: str, path: str,
|
||||||
'<header>\n' + \
|
'<header>\n' + \
|
||||||
'<a href="/users/' + nickname + '/' + defaultTimeline + '" title="' + \
|
'<a href="/users/' + nickname + '/' + defaultTimeline + '" title="' + \
|
||||||
translate['Switch to timeline view'] + '" alt="' + \
|
translate['Switch to timeline view'] + '" alt="' + \
|
||||||
translate['Switch to timeline view'] + '">\n'
|
translate['Switch to timeline view'] + '" ' + \
|
||||||
|
'accesskey="' + accessKeys['menuTimeline'] + '">\n'
|
||||||
editLinksForm += '<img loading="lazy" class="timeline-banner" ' + \
|
editLinksForm += '<img loading="lazy" class="timeline-banner" ' + \
|
||||||
'alt = "" src="' + \
|
'alt = "" src="' + \
|
||||||
'/users/' + nickname + '/' + bannerFile + '" /></a>\n' + \
|
'/users/' + nickname + '/' + bannerFile + '" /></a>\n' + \
|
||||||
|
|
@ -384,7 +394,8 @@ def htmlEditLinks(cssCache: {}, translate: {}, baseDir: str, path: str,
|
||||||
' <h1>' + translate['Edit Links'] + '</h1>'
|
' <h1>' + translate['Edit Links'] + '</h1>'
|
||||||
editLinksForm += \
|
editLinksForm += \
|
||||||
' <input type="submit" name="submitLinks" value="' + \
|
' <input type="submit" name="submitLinks" value="' + \
|
||||||
translate['Submit'] + '">\n'
|
translate['Submit'] + '" ' + \
|
||||||
|
'accesskey="' + accessKeys['submitButton'] + '">\n'
|
||||||
editLinksForm += \
|
editLinksForm += \
|
||||||
' </div>\n'
|
' </div>\n'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,8 @@ def getRightColumnContent(baseDir: str, nickname: str, domainFull: str,
|
||||||
authorized: bool,
|
authorized: bool,
|
||||||
showHeaderImage: bool,
|
showHeaderImage: bool,
|
||||||
theme: str,
|
theme: str,
|
||||||
defaultTimeline: str) -> str:
|
defaultTimeline: str,
|
||||||
|
accessKeys: {}) -> str:
|
||||||
"""Returns html content for the right column
|
"""Returns html content for the right column
|
||||||
"""
|
"""
|
||||||
htmlStr = ''
|
htmlStr = ''
|
||||||
|
|
@ -69,7 +70,8 @@ def getRightColumnContent(baseDir: str, nickname: str, domainFull: str,
|
||||||
publishButtonStr = \
|
publishButtonStr = \
|
||||||
' <a href="' + \
|
' <a href="' + \
|
||||||
'/users/' + nickname + '/newblog?nodropdown" ' + \
|
'/users/' + nickname + '/newblog?nodropdown" ' + \
|
||||||
'title="' + titleStr + '">' + \
|
'title="' + titleStr + '" ' + \
|
||||||
|
'accesskey="' + accessKeys['menuNewPost'] + '">' + \
|
||||||
'<button class="publishbtn">' + \
|
'<button class="publishbtn">' + \
|
||||||
translate['Publish'] + '</button></a>\n'
|
translate['Publish'] + '</button></a>\n'
|
||||||
else:
|
else:
|
||||||
|
|
@ -124,7 +126,8 @@ def getRightColumnContent(baseDir: str, nickname: str, domainFull: str,
|
||||||
# show the edit icon highlighted
|
# show the edit icon highlighted
|
||||||
htmlStr += \
|
htmlStr += \
|
||||||
' <a href="' + \
|
' <a href="' + \
|
||||||
'/users/' + nickname + '/editnewswire">' + \
|
'/users/' + nickname + '/editnewswire" ' + \
|
||||||
|
'accesskey="' + accessKeys['menuEdit'] + '">' + \
|
||||||
'<img class="' + editImageClass + \
|
'<img class="' + editImageClass + \
|
||||||
'" loading="lazy" alt="' + \
|
'" loading="lazy" alt="' + \
|
||||||
translate['Edit newswire'] + ' | " title="' + \
|
translate['Edit newswire'] + ' | " title="' + \
|
||||||
|
|
@ -134,7 +137,8 @@ def getRightColumnContent(baseDir: str, nickname: str, domainFull: str,
|
||||||
# show the edit icon
|
# show the edit icon
|
||||||
htmlStr += \
|
htmlStr += \
|
||||||
' <a href="' + \
|
' <a href="' + \
|
||||||
'/users/' + nickname + '/editnewswire">' + \
|
'/users/' + nickname + '/editnewswire" ' + \
|
||||||
|
'accesskey="' + accessKeys['menuEdit'] + '">' + \
|
||||||
'<img class="' + editImageClass + \
|
'<img class="' + editImageClass + \
|
||||||
'" loading="lazy" alt="' + \
|
'" loading="lazy" alt="' + \
|
||||||
translate['Edit newswire'] + ' | " title="' + \
|
translate['Edit newswire'] + ' | " title="' + \
|
||||||
|
|
@ -167,7 +171,8 @@ def getRightColumnContent(baseDir: str, nickname: str, domainFull: str,
|
||||||
titleStr = translate['Publish a news article']
|
titleStr = translate['Publish a news article']
|
||||||
htmlStr += \
|
htmlStr += \
|
||||||
' <a href="' + \
|
' <a href="' + \
|
||||||
'/users/' + nickname + '/newblog?nodropdown">' + \
|
'/users/' + nickname + '/newblog?nodropdown" ' + \
|
||||||
|
'accesskey="' + accessKeys['menuNewPost'] + '">' + \
|
||||||
'<img class="' + editImageClass + \
|
'<img class="' + editImageClass + \
|
||||||
'" loading="lazy" alt="' + \
|
'" loading="lazy" alt="' + \
|
||||||
titleStr + '" title="' + \
|
titleStr + '" title="' + \
|
||||||
|
|
@ -444,7 +449,8 @@ def htmlNewswireMobile(cssCache: {}, baseDir: str, nickname: str,
|
||||||
rssIconAtTop: bool,
|
rssIconAtTop: bool,
|
||||||
iconsAsButtons: bool,
|
iconsAsButtons: bool,
|
||||||
defaultTimeline: str,
|
defaultTimeline: str,
|
||||||
theme: str) -> str:
|
theme: str,
|
||||||
|
accessKeys: {}) -> str:
|
||||||
"""Shows the mobile version of the newswire right column
|
"""Shows the mobile version of the newswire right column
|
||||||
"""
|
"""
|
||||||
htmlStr = ''
|
htmlStr = ''
|
||||||
|
|
@ -473,7 +479,8 @@ def htmlNewswireMobile(cssCache: {}, baseDir: str, nickname: str,
|
||||||
bannerFile, bannerFilename = \
|
bannerFile, bannerFilename = \
|
||||||
getBannerFile(baseDir, nickname, domain, theme)
|
getBannerFile(baseDir, nickname, domain, theme)
|
||||||
htmlStr += \
|
htmlStr += \
|
||||||
'<a href="/users/' + nickname + '/' + defaultTimeline + '">' + \
|
'<a href="/users/' + nickname + '/' + defaultTimeline + '" ' + \
|
||||||
|
'accesskey="' + accessKeys['menuTimeline'] + '">' + \
|
||||||
'<img loading="lazy" class="timeline-banner" ' + \
|
'<img loading="lazy" class="timeline-banner" ' + \
|
||||||
'alt="' + translate['Timeline banner image'] + '" ' + \
|
'alt="' + translate['Timeline banner image'] + '" ' + \
|
||||||
'src="/users/' + nickname + '/' + bannerFile + '" /></a>\n'
|
'src="/users/' + nickname + '/' + bannerFile + '" /></a>\n'
|
||||||
|
|
@ -493,7 +500,7 @@ def htmlNewswireMobile(cssCache: {}, baseDir: str, nickname: str,
|
||||||
False, timelinePath, showPublishButton,
|
False, timelinePath, showPublishButton,
|
||||||
showPublishAsIcon, rssIconAtTop, False,
|
showPublishAsIcon, rssIconAtTop, False,
|
||||||
authorized, False, theme,
|
authorized, False, theme,
|
||||||
defaultTimeline)
|
defaultTimeline, accessKeys)
|
||||||
else:
|
else:
|
||||||
if editor:
|
if editor:
|
||||||
htmlStr += '<br><br><br>\n'
|
htmlStr += '<br><br><br>\n'
|
||||||
|
|
@ -509,7 +516,8 @@ def htmlNewswireMobile(cssCache: {}, baseDir: str, nickname: str,
|
||||||
|
|
||||||
def htmlEditNewswire(cssCache: {}, translate: {}, baseDir: str, path: str,
|
def htmlEditNewswire(cssCache: {}, translate: {}, baseDir: str, path: str,
|
||||||
domain: str, port: int, httpPrefix: str,
|
domain: str, port: int, httpPrefix: str,
|
||||||
defaultTimeline: str, theme: str) -> str:
|
defaultTimeline: str, theme: str,
|
||||||
|
accessKeys: {}) -> str:
|
||||||
"""Shows the edit newswire screen
|
"""Shows the edit newswire screen
|
||||||
"""
|
"""
|
||||||
if '/users/' not in path:
|
if '/users/' not in path:
|
||||||
|
|
@ -542,7 +550,8 @@ def htmlEditNewswire(cssCache: {}, translate: {}, baseDir: str, path: str,
|
||||||
'<header>' + \
|
'<header>' + \
|
||||||
'<a href="/users/' + nickname + '/' + defaultTimeline + '" title="' + \
|
'<a href="/users/' + nickname + '/' + defaultTimeline + '" title="' + \
|
||||||
translate['Switch to timeline view'] + '" alt="' + \
|
translate['Switch to timeline view'] + '" alt="' + \
|
||||||
translate['Switch to timeline view'] + '">\n'
|
translate['Switch to timeline view'] + '" ' + \
|
||||||
|
'accesskey="' + accessKeys['menuTimeline'] + '">\n'
|
||||||
editNewswireForm += '<img loading="lazy" class="timeline-banner" src="' + \
|
editNewswireForm += '<img loading="lazy" class="timeline-banner" src="' + \
|
||||||
'/users/' + nickname + '/' + bannerFile + '" ' + \
|
'/users/' + nickname + '/' + bannerFile + '" ' + \
|
||||||
'alt="" /></a>\n</header>'
|
'alt="" /></a>\n</header>'
|
||||||
|
|
@ -558,7 +567,8 @@ def htmlEditNewswire(cssCache: {}, translate: {}, baseDir: str, path: str,
|
||||||
' <div class="containerSubmitNewPost">\n'
|
' <div class="containerSubmitNewPost">\n'
|
||||||
editNewswireForm += \
|
editNewswireForm += \
|
||||||
' <input type="submit" name="submitNewswire" value="' + \
|
' <input type="submit" name="submitNewswire" value="' + \
|
||||||
translate['Submit'] + '">\n'
|
translate['Submit'] + '" ' + \
|
||||||
|
'accesskey="' + accessKeys['submitButton'] + '">\n'
|
||||||
editNewswireForm += \
|
editNewswireForm += \
|
||||||
' </div>\n'
|
' </div>\n'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,8 @@ def _htmlNewPostDropDown(scopeIcon: str, scopeDescription: str,
|
||||||
dropdownReminderSuffix: str,
|
dropdownReminderSuffix: str,
|
||||||
dropdownEventSuffix: str,
|
dropdownEventSuffix: str,
|
||||||
dropdownReportSuffix: str,
|
dropdownReportSuffix: str,
|
||||||
noDropDown: bool) -> str:
|
noDropDown: bool,
|
||||||
|
accessKeys: {}) -> str:
|
||||||
"""Returns the html for a drop down list of new post types
|
"""Returns the html for a drop down list of new post types
|
||||||
"""
|
"""
|
||||||
dropDownContent = '<nav><div class="newPostDropdown">\n'
|
dropDownContent = '<nav><div class="newPostDropdown">\n'
|
||||||
|
|
@ -93,21 +94,24 @@ def _htmlNewPostDropDown(scopeIcon: str, scopeDescription: str,
|
||||||
if showPublicOnDropdown:
|
if showPublicOnDropdown:
|
||||||
dropDownContent += \
|
dropDownContent += \
|
||||||
'<li><a href="' + pathBase + dropdownNewPostSuffix + \
|
'<li><a href="' + pathBase + dropdownNewPostSuffix + \
|
||||||
'"><img loading="lazy" alt="" title="" src="/' + \
|
'" accesskey="' + accessKeys['Public'] + '">' + \
|
||||||
|
'<img loading="lazy" alt="" title="" src="/' + \
|
||||||
'icons/scope_public.png"/><b>' + \
|
'icons/scope_public.png"/><b>' + \
|
||||||
translate['Public'] + '</b><br>' + \
|
translate['Public'] + '</b><br>' + \
|
||||||
translate['Visible to anyone'] + '</a></li>\n'
|
translate['Visible to anyone'] + '</a></li>\n'
|
||||||
if defaultTimeline == 'tlfeatures':
|
if defaultTimeline == 'tlfeatures':
|
||||||
dropDownContent += \
|
dropDownContent += \
|
||||||
'<li><a href="' + pathBase + dropdownNewBlogSuffix + \
|
'<li><a href="' + pathBase + dropdownNewBlogSuffix + \
|
||||||
'"><img loading="lazy" alt="" title="" src="/' + \
|
'" accesskey="' + accessKeys['menuBlogs'] + '">' + \
|
||||||
|
'<img loading="lazy" alt="" title="" src="/' + \
|
||||||
'icons/scope_blog.png"/><b>' + \
|
'icons/scope_blog.png"/><b>' + \
|
||||||
translate['Article'] + '</b><br>' + \
|
translate['Article'] + '</b><br>' + \
|
||||||
translate['Create an article'] + '</a></li>\n'
|
translate['Create an article'] + '</a></li>\n'
|
||||||
else:
|
else:
|
||||||
dropDownContent += \
|
dropDownContent += \
|
||||||
'<li><a href="' + pathBase + dropdownNewBlogSuffix + \
|
'<li><a href="' + pathBase + dropdownNewBlogSuffix + \
|
||||||
'"><img loading="lazy" alt="" title="" src="/' + \
|
'" accesskey="' + accessKeys['menuBlogs'] + '">' + \
|
||||||
|
'<img loading="lazy" alt="" title="" src="/' + \
|
||||||
'icons/scope_blog.png"/><b>' + \
|
'icons/scope_blog.png"/><b>' + \
|
||||||
translate['Blog'] + '</b><br>' + \
|
translate['Blog'] + '</b><br>' + \
|
||||||
translate['Publicly visible post'] + '</a></li>\n'
|
translate['Publicly visible post'] + '</a></li>\n'
|
||||||
|
|
@ -119,20 +123,23 @@ def _htmlNewPostDropDown(scopeIcon: str, scopeDescription: str,
|
||||||
translate['Not on public timeline'] + '</a></li>\n'
|
translate['Not on public timeline'] + '</a></li>\n'
|
||||||
dropDownContent += \
|
dropDownContent += \
|
||||||
'<li><a href="' + pathBase + dropdownFollowersSuffix + \
|
'<li><a href="' + pathBase + dropdownFollowersSuffix + \
|
||||||
'"><img loading="lazy" alt="" title="" src="/' + \
|
'" accesskey="' + accessKeys['menuFollowers'] + '">' + \
|
||||||
|
'<img loading="lazy" alt="" title="" src="/' + \
|
||||||
'icons/scope_followers.png"/><b>' + \
|
'icons/scope_followers.png"/><b>' + \
|
||||||
translate['Followers'] + '</b><br>' + \
|
translate['Followers'] + '</b><br>' + \
|
||||||
translate['Only to followers'] + '</a></li>\n'
|
translate['Only to followers'] + '</a></li>\n'
|
||||||
dropDownContent += \
|
dropDownContent += \
|
||||||
'<li><a href="' + pathBase + dropdownDMSuffix + \
|
'<li><a href="' + pathBase + dropdownDMSuffix + \
|
||||||
'"><img loading="lazy" alt="" title="" src="/' + \
|
'" accesskey="' + accessKeys['menuDM'] + '">' + \
|
||||||
|
'<img loading="lazy" alt="" title="" src="/' + \
|
||||||
'icons/scope_dm.png"/><b>' + \
|
'icons/scope_dm.png"/><b>' + \
|
||||||
translate['DM'] + '</b><br>' + \
|
translate['DM'] + '</b><br>' + \
|
||||||
translate['Only to mentioned people'] + '</a></li>\n'
|
translate['Only to mentioned people'] + '</a></li>\n'
|
||||||
|
|
||||||
dropDownContent += \
|
dropDownContent += \
|
||||||
'<li><a href="' + pathBase + dropdownReminderSuffix + \
|
'<li><a href="' + pathBase + dropdownReminderSuffix + \
|
||||||
'"><img loading="lazy" alt="" title="" src="/' + \
|
'" accesskey="' + accessKeys['Reminder'] + '">' + \
|
||||||
|
'<img loading="lazy" alt="" title="" src="/' + \
|
||||||
'icons/scope_reminder.png"/><b>' + \
|
'icons/scope_reminder.png"/><b>' + \
|
||||||
translate['Reminder'] + '</b><br>' + \
|
translate['Reminder'] + '</b><br>' + \
|
||||||
translate['Scheduled note to yourself'] + '</a></li>\n'
|
translate['Scheduled note to yourself'] + '</a></li>\n'
|
||||||
|
|
@ -144,7 +151,8 @@ def _htmlNewPostDropDown(scopeIcon: str, scopeDescription: str,
|
||||||
# translate['Create an event'] + '</a></li>\n'
|
# translate['Create an event'] + '</a></li>\n'
|
||||||
dropDownContent += \
|
dropDownContent += \
|
||||||
'<li><a href="' + pathBase + dropdownReportSuffix + \
|
'<li><a href="' + pathBase + dropdownReportSuffix + \
|
||||||
'"><img loading="lazy" alt="" title="" src="/' + \
|
'" accesskey="' + accessKeys['reportButton'] + '">' + \
|
||||||
|
'<img loading="lazy" alt="" title="" src="/' + \
|
||||||
'icons/scope_report.png"/><b>' + \
|
'icons/scope_report.png"/><b>' + \
|
||||||
translate['Report'] + '</b><br>' + \
|
translate['Report'] + '</b><br>' + \
|
||||||
translate['Send to moderators'] + '</a></li>\n'
|
translate['Send to moderators'] + '</a></li>\n'
|
||||||
|
|
@ -152,7 +160,8 @@ def _htmlNewPostDropDown(scopeIcon: str, scopeDescription: str,
|
||||||
if not replyStr:
|
if not replyStr:
|
||||||
dropDownContent += \
|
dropDownContent += \
|
||||||
'<li><a href="' + pathBase + \
|
'<li><a href="' + pathBase + \
|
||||||
'/newshare"><img loading="lazy" alt="" title="" src="/' + \
|
'/newshare" accesskey="' + accessKeys['menuShares'] + '">' + \
|
||||||
|
'<img loading="lazy" alt="" title="" src="/' + \
|
||||||
'icons/scope_share.png"/><b>' + \
|
'icons/scope_share.png"/><b>' + \
|
||||||
translate['Shares'] + '</b><br>' + \
|
translate['Shares'] + '</b><br>' + \
|
||||||
translate['Describe a shared item'] + '</a></li>\n'
|
translate['Describe a shared item'] + '</a></li>\n'
|
||||||
|
|
@ -177,7 +186,8 @@ def htmlNewPost(cssCache: {}, mediaInstance: bool, translate: {},
|
||||||
nickname: str, domain: str,
|
nickname: str, domain: str,
|
||||||
domainFull: str,
|
domainFull: str,
|
||||||
defaultTimeline: str, newswire: {},
|
defaultTimeline: str, newswire: {},
|
||||||
theme: str, noDropDown: bool) -> str:
|
theme: str, noDropDown: bool,
|
||||||
|
accessKeys: {}) -> str:
|
||||||
"""New post screen
|
"""New post screen
|
||||||
"""
|
"""
|
||||||
replyStr = ''
|
replyStr = ''
|
||||||
|
|
@ -579,7 +589,8 @@ def htmlNewPost(cssCache: {}, mediaInstance: bool, translate: {},
|
||||||
'<header>\n' + \
|
'<header>\n' + \
|
||||||
'<a href="/users/' + nickname + '/' + defaultTimeline + '" title="' + \
|
'<a href="/users/' + nickname + '/' + defaultTimeline + '" title="' + \
|
||||||
translate['Switch to timeline view'] + '" alt="' + \
|
translate['Switch to timeline view'] + '" alt="' + \
|
||||||
translate['Switch to timeline view'] + '">\n'
|
translate['Switch to timeline view'] + '" ' + \
|
||||||
|
'accesskey="' + accessKeys['menuTimeline'] + '">\n'
|
||||||
newPostForm += '<img loading="lazy" class="timeline-banner" src="' + \
|
newPostForm += '<img loading="lazy" class="timeline-banner" src="' + \
|
||||||
'/users/' + nickname + '/' + bannerFile + '" alt="" /></a>\n' + \
|
'/users/' + nickname + '/' + bannerFile + '" alt="" /></a>\n' + \
|
||||||
'</header>\n'
|
'</header>\n'
|
||||||
|
|
@ -651,7 +662,7 @@ def htmlNewPost(cssCache: {}, mediaInstance: bool, translate: {},
|
||||||
dropdownReminderSuffix,
|
dropdownReminderSuffix,
|
||||||
dropdownEventSuffix,
|
dropdownEventSuffix,
|
||||||
dropdownReportSuffix,
|
dropdownReportSuffix,
|
||||||
noDropDown)
|
noDropDown, accessKeys)
|
||||||
else:
|
else:
|
||||||
if not shareDescription:
|
if not shareDescription:
|
||||||
# reporting a post to moderator
|
# reporting a post to moderator
|
||||||
|
|
@ -693,7 +704,8 @@ def htmlNewPost(cssCache: {}, mediaInstance: bool, translate: {},
|
||||||
|
|
||||||
newPostForm += \
|
newPostForm += \
|
||||||
' <td><input type="submit" name="submitPost" value="' + \
|
' <td><input type="submit" name="submitPost" value="' + \
|
||||||
translate['Submit'] + '"></td>\n'
|
translate['Submit'] + '" ' + \
|
||||||
|
'accesskey="' + accessKeys['submitButton'] + '"></td>\n'
|
||||||
|
|
||||||
newPostForm += ' </tr>\n'
|
newPostForm += ' </tr>\n'
|
||||||
newPostForm += '</table>\n'
|
newPostForm += '</table>\n'
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,7 @@ def htmlFrontScreen(rssIconAtTop: bool,
|
||||||
newswire: {}, theme: str,
|
newswire: {}, theme: str,
|
||||||
peertubeInstances: [],
|
peertubeInstances: [],
|
||||||
allowLocalNetworkAccess: bool,
|
allowLocalNetworkAccess: bool,
|
||||||
|
accessKeys: {},
|
||||||
extraJson=None,
|
extraJson=None,
|
||||||
pageNumber=None, maxItemsPerPage=None) -> str:
|
pageNumber=None, maxItemsPerPage=None) -> str:
|
||||||
"""Show the news instance front screen
|
"""Show the news instance front screen
|
||||||
|
|
@ -138,7 +139,7 @@ def htmlFrontScreen(rssIconAtTop: bool,
|
||||||
getLeftColumnContent(baseDir, 'news', domainFull,
|
getLeftColumnContent(baseDir, 'news', domainFull,
|
||||||
httpPrefix, translate,
|
httpPrefix, translate,
|
||||||
False, False, None, rssIconAtTop, True,
|
False, False, None, rssIconAtTop, True,
|
||||||
True, theme)
|
True, theme, accessKeys)
|
||||||
profileHeaderStr += ' </td>\n'
|
profileHeaderStr += ' </td>\n'
|
||||||
profileHeaderStr += ' <td valign="top" class="col-center">\n'
|
profileHeaderStr += ' <td valign="top" class="col-center">\n'
|
||||||
|
|
||||||
|
|
@ -173,7 +174,7 @@ def htmlFrontScreen(rssIconAtTop: bool,
|
||||||
False, False, newswire, False,
|
False, False, newswire, False,
|
||||||
False, None, False, False,
|
False, None, False, False,
|
||||||
False, True, authorized, True, theme,
|
False, True, authorized, True, theme,
|
||||||
defaultTimeline)
|
defaultTimeline, accessKeys)
|
||||||
profileFooterStr += ' </td>\n'
|
profileFooterStr += ' </td>\n'
|
||||||
profileFooterStr += ' </tr>\n'
|
profileFooterStr += ' </tr>\n'
|
||||||
profileFooterStr += ' </tbody>\n'
|
profileFooterStr += ' </tbody>\n'
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,8 @@ def headerButtonsTimeline(defaultTimeline: str,
|
||||||
calendarPath: str,
|
calendarPath: str,
|
||||||
calendarImage: str,
|
calendarImage: str,
|
||||||
followApprovals: str,
|
followApprovals: str,
|
||||||
iconsAsButtons: bool) -> str:
|
iconsAsButtons: bool,
|
||||||
|
accessKeys: {}) -> str:
|
||||||
"""Returns the header at the top of the timeline, containing
|
"""Returns the header at the top of the timeline, containing
|
||||||
buttons for inbox, outbox, search, calendar, etc
|
buttons for inbox, outbox, search, calendar, etc
|
||||||
"""
|
"""
|
||||||
|
|
@ -53,7 +54,9 @@ def headerButtonsTimeline(defaultTimeline: str,
|
||||||
if defaultTimeline == 'tlmedia':
|
if defaultTimeline == 'tlmedia':
|
||||||
tlStr += \
|
tlStr += \
|
||||||
'<a href="' + usersPath + \
|
'<a href="' + usersPath + \
|
||||||
'/tlmedia" tabindex="-1"><button class="' + \
|
'/tlmedia" tabindex="-1" ' + \
|
||||||
|
'accesskey="' + accessKeys['menuMedia'] + '"' + \
|
||||||
|
'><button class="' + \
|
||||||
mediaButton + '"><span>' + translate['Media'] + \
|
mediaButton + '"><span>' + translate['Media'] + \
|
||||||
'</span></button></a>'
|
'</span></button></a>'
|
||||||
elif defaultTimeline == 'tlblogs':
|
elif defaultTimeline == 'tlblogs':
|
||||||
|
|
@ -102,7 +105,9 @@ def headerButtonsTimeline(defaultTimeline: str,
|
||||||
if not minimal and not featuresHeader:
|
if not minimal and not featuresHeader:
|
||||||
tlStr += \
|
tlStr += \
|
||||||
'<a href="' + usersPath + \
|
'<a href="' + usersPath + \
|
||||||
'/tlmedia" tabindex="-1"><button class="' + \
|
'/tlmedia" tabindex="-1" ' + \
|
||||||
|
'accesskey="' + accessKeys['menuMedia'] + '">' + \
|
||||||
|
'<button class="' + \
|
||||||
mediaButton + '"><span>' + translate['Media'] + \
|
mediaButton + '"><span>' + translate['Media'] + \
|
||||||
'</span></button></a>'
|
'</span></button></a>'
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ def htmlLogin(cssCache: {}, translate: {},
|
||||||
copyfile(baseDir + '/img/login.png', loginImageFilename)
|
copyfile(baseDir + '/img/login.png', loginImageFilename)
|
||||||
|
|
||||||
textModeLogo = getTextModeLogo(baseDir)
|
textModeLogo = getTextModeLogo(baseDir)
|
||||||
textModeLogoHtml = htmlKeyboardNavigation(textModeLogo, {})
|
textModeLogoHtml = htmlKeyboardNavigation(textModeLogo, {}, {})
|
||||||
|
|
||||||
if os.path.isfile(baseDir + '/accounts/login-background-custom.jpg'):
|
if os.path.isfile(baseDir + '/accounts/login-background-custom.jpg'):
|
||||||
if not os.path.isfile(baseDir + '/accounts/login-background.jpg'):
|
if not os.path.isfile(baseDir + '/accounts/login-background.jpg'):
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,8 @@ def htmlModeration(cssCache: {}, defaultTimeline: str,
|
||||||
authorized: bool, moderationActionStr: str,
|
authorized: bool, moderationActionStr: str,
|
||||||
theme: str, peertubeInstances: [],
|
theme: str, peertubeInstances: [],
|
||||||
allowLocalNetworkAccess: bool,
|
allowLocalNetworkAccess: bool,
|
||||||
textModeBanner: str) -> str:
|
textModeBanner: str,
|
||||||
|
accessKeys: {}) -> str:
|
||||||
"""Show the moderation feed as html
|
"""Show the moderation feed as html
|
||||||
This is what you see when selecting the "mod" timeline
|
This is what you see when selecting the "mod" timeline
|
||||||
"""
|
"""
|
||||||
|
|
@ -60,7 +61,7 @@ def htmlModeration(cssCache: {}, defaultTimeline: str,
|
||||||
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
||||||
authorized, moderationActionStr, theme,
|
authorized, moderationActionStr, theme,
|
||||||
peertubeInstances, allowLocalNetworkAccess,
|
peertubeInstances, allowLocalNetworkAccess,
|
||||||
textModeBanner)
|
textModeBanner, accessKeys)
|
||||||
|
|
||||||
|
|
||||||
def htmlAccountInfo(cssCache: {}, translate: {},
|
def htmlAccountInfo(cssCache: {}, translate: {},
|
||||||
|
|
@ -270,7 +271,9 @@ def htmlModerationInfo(cssCache: {}, translate: {},
|
||||||
for acct in dirs:
|
for acct in dirs:
|
||||||
if '@' not in acct:
|
if '@' not in acct:
|
||||||
continue
|
continue
|
||||||
if 'inbox@' in acct or 'news@' in acct:
|
if acct.startswith('inbox@'):
|
||||||
|
continue
|
||||||
|
elif acct.startswith('news@'):
|
||||||
continue
|
continue
|
||||||
accounts.append(acct)
|
accounts.append(acct)
|
||||||
break
|
break
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,8 @@ def htmlPersonOptions(defaultTimeline: str,
|
||||||
alsoKnownAs: [],
|
alsoKnownAs: [],
|
||||||
textModeBanner: str,
|
textModeBanner: str,
|
||||||
newsInstance: bool,
|
newsInstance: bool,
|
||||||
authorized: bool) -> str:
|
authorized: bool,
|
||||||
|
accessKeys: {}) -> str:
|
||||||
"""Show options for a person: view/follow/block/report
|
"""Show options for a person: view/follow/block/report
|
||||||
"""
|
"""
|
||||||
optionsDomain, optionsPort = getDomainFromActor(optionsActor)
|
optionsDomain, optionsPort = getDomainFromActor(optionsActor)
|
||||||
|
|
@ -119,7 +120,7 @@ def htmlPersonOptions(defaultTimeline: str,
|
||||||
instanceTitle = \
|
instanceTitle = \
|
||||||
getConfigParam(baseDir, 'instanceTitle')
|
getConfigParam(baseDir, 'instanceTitle')
|
||||||
optionsStr = htmlHeaderWithExternalStyle(cssFilename, instanceTitle)
|
optionsStr = htmlHeaderWithExternalStyle(cssFilename, instanceTitle)
|
||||||
optionsStr += htmlKeyboardNavigation(textModeBanner, {})
|
optionsStr += htmlKeyboardNavigation(textModeBanner, {}, {})
|
||||||
optionsStr += '<br><br>\n'
|
optionsStr += '<br><br>\n'
|
||||||
optionsStr += '<div class="options">\n'
|
optionsStr += '<div class="options">\n'
|
||||||
optionsStr += ' <div class="optionsAvatar">\n'
|
optionsStr += ' <div class="optionsAvatar">\n'
|
||||||
|
|
@ -234,7 +235,8 @@ def htmlPersonOptions(defaultTimeline: str,
|
||||||
optionsStr += \
|
optionsStr += \
|
||||||
' ' + translate['Petname'] + ': \n' + \
|
' ' + translate['Petname'] + ': \n' + \
|
||||||
' <input type="text" name="optionpetname" value="' + \
|
' <input type="text" name="optionpetname" value="' + \
|
||||||
petname + '">\n' \
|
petname + '" ' + \
|
||||||
|
'accesskey="' + accessKeys['enterPetname'] + '">\n' \
|
||||||
' <button type="submit" class="buttonsmall" ' + \
|
' <button type="submit" class="buttonsmall" ' + \
|
||||||
'name="submitPetname">' + \
|
'name="submitPetname">' + \
|
||||||
translate['Submit'] + '</button><br>\n'
|
translate['Submit'] + '</button><br>\n'
|
||||||
|
|
@ -324,40 +326,51 @@ def htmlPersonOptions(defaultTimeline: str,
|
||||||
if authorized and originPathStr == '/users/' + nickname:
|
if authorized and originPathStr == '/users/' + nickname:
|
||||||
optionsStr += \
|
optionsStr += \
|
||||||
' <a href="' + backPath + '"><button type="button" ' + \
|
' <a href="' + backPath + '"><button type="button" ' + \
|
||||||
'class="buttonIcon" name="submitBack">' + translate['Go Back'] + \
|
'class="buttonIcon" name="submitBack" ' + \
|
||||||
'</button></a>\n'
|
'accesskey="' + accessKeys['menuTimeline'] + '">' + \
|
||||||
|
translate['Go Back'] + '</button></a>\n'
|
||||||
else:
|
else:
|
||||||
optionsStr += \
|
optionsStr += \
|
||||||
' <a href="' + originPathStr + '"><button type="button" ' + \
|
' <a href="' + originPathStr + '"><button type="button" ' + \
|
||||||
'class="buttonIcon" name="submitBack">' + translate['Go Back'] + \
|
'class="buttonIcon" name="submitBack" accesskey="' + \
|
||||||
|
accessKeys['menuTimeline'] + '">' + translate['Go Back'] + \
|
||||||
'</button></a>\n'
|
'</button></a>\n'
|
||||||
if authorized:
|
if authorized:
|
||||||
optionsStr += \
|
optionsStr += \
|
||||||
' <button type="submit" class="button" name="submitView">' + \
|
' <button type="submit" class="button" ' + \
|
||||||
|
'name="submitView" accesskey="' + \
|
||||||
|
accessKeys['viewButton'] + '">' + \
|
||||||
translate['View'] + '</button>\n'
|
translate['View'] + '</button>\n'
|
||||||
optionsStr += donateStr
|
optionsStr += donateStr
|
||||||
if authorized:
|
if authorized:
|
||||||
optionsStr += \
|
optionsStr += \
|
||||||
' <button type="submit" class="button" name="submit' + \
|
' <button type="submit" class="button" name="submit' + \
|
||||||
followStr + '">' + translate[followStr] + '</button>\n'
|
followStr + '" accesskey="' + accessKeys['followButton'] + '">' + \
|
||||||
|
translate[followStr] + '</button>\n'
|
||||||
optionsStr += \
|
optionsStr += \
|
||||||
' <button type="submit" class="button" name="submit' + \
|
' <button type="submit" class="button" name="submit' + \
|
||||||
blockStr + '">' + translate[blockStr] + '</button>\n'
|
blockStr + '" accesskey="' + accessKeys['blockButton'] + '">' + \
|
||||||
|
translate[blockStr] + '</button>\n'
|
||||||
optionsStr += \
|
optionsStr += \
|
||||||
' <button type="submit" class="button" name="submitDM">' + \
|
' <button type="submit" class="button" name="submitDM" ' + \
|
||||||
|
'accesskey="' + accessKeys['menuDM'] + '">' + \
|
||||||
translate['DM'] + '</button>\n'
|
translate['DM'] + '</button>\n'
|
||||||
optionsStr += \
|
optionsStr += \
|
||||||
' <button type="submit" class="button" name="submit' + \
|
' <button type="submit" class="button" name="submit' + \
|
||||||
snoozeButtonStr + '">' + translate[snoozeButtonStr] + \
|
snoozeButtonStr + '" accesskey="' + \
|
||||||
|
accessKeys['snoozeButton'] + '">' + translate[snoozeButtonStr] + \
|
||||||
'</button>\n'
|
'</button>\n'
|
||||||
optionsStr += \
|
optionsStr += \
|
||||||
' <button type="submit" class="button" ' + \
|
' <button type="submit" class="button" ' + \
|
||||||
'name="submitReport">' + translate['Report'] + '</button>\n'
|
'name="submitReport" accesskey="' + \
|
||||||
|
accessKeys['reportButton'] + '">' + \
|
||||||
|
translate['Report'] + '</button>\n'
|
||||||
|
|
||||||
if isModerator(baseDir, nickname):
|
if isModerator(baseDir, nickname):
|
||||||
optionsStr += \
|
optionsStr += \
|
||||||
' <button type="submit" class="button" ' + \
|
' <button type="submit" class="button" ' + \
|
||||||
'name="submitPersonInfo">' + \
|
'name="submitPersonInfo" accesskey="' + \
|
||||||
|
accessKeys['infoButton'] + '">' + \
|
||||||
translate['Info'] + '</button>\n'
|
translate['Info'] + '</button>\n'
|
||||||
|
|
||||||
personNotes = ''
|
personNotes = ''
|
||||||
|
|
@ -376,7 +389,8 @@ def htmlPersonOptions(defaultTimeline: str,
|
||||||
translate['Submit'] + '</button><br>\n'
|
translate['Submit'] + '</button><br>\n'
|
||||||
optionsStr += \
|
optionsStr += \
|
||||||
' <textarea id="message" ' + \
|
' <textarea id="message" ' + \
|
||||||
'name="optionnotes" style="height:400px" spellcheck="true">' + \
|
'name="optionnotes" style="height:400px" spellcheck="true" ' + \
|
||||||
|
'accesskey="' + accessKeys['enterNotes'] + '">' + \
|
||||||
personNotes + '</textarea>\n'
|
personNotes + '</textarea>\n'
|
||||||
|
|
||||||
optionsStr += ' </form>\n'
|
optionsStr += ' </form>\n'
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,8 @@ def htmlProfileAfterSearch(cssCache: {},
|
||||||
defaultTimeline: str,
|
defaultTimeline: str,
|
||||||
peertubeInstances: [],
|
peertubeInstances: [],
|
||||||
allowLocalNetworkAccess: bool,
|
allowLocalNetworkAccess: bool,
|
||||||
themeName: str) -> str:
|
themeName: str,
|
||||||
|
accessKeys: {}) -> str:
|
||||||
"""Show a profile page after a search for a fediverse address
|
"""Show a profile page after a search for a fediverse address
|
||||||
"""
|
"""
|
||||||
if hasUsersPath(profileHandle) or '/@' in profileHandle:
|
if hasUsersPath(profileHandle) or '/@' in profileHandle:
|
||||||
|
|
@ -255,7 +256,7 @@ def htmlProfileAfterSearch(cssCache: {},
|
||||||
profileDescriptionShort,
|
profileDescriptionShort,
|
||||||
avatarUrl, imageUrl,
|
avatarUrl, imageUrl,
|
||||||
movedTo, profileJson['id'],
|
movedTo, profileJson['id'],
|
||||||
alsoKnownAs)
|
alsoKnownAs, accessKeys)
|
||||||
|
|
||||||
domainFull = getFullDomain(domain, port)
|
domainFull = getFullDomain(domain, port)
|
||||||
|
|
||||||
|
|
@ -276,10 +277,12 @@ def htmlProfileAfterSearch(cssCache: {},
|
||||||
' <input type="hidden" name="actor" value="' + \
|
' <input type="hidden" name="actor" value="' + \
|
||||||
personUrl + '">\n'
|
personUrl + '">\n'
|
||||||
profileStr += \
|
profileStr += \
|
||||||
' <button type="submit" class="button" name="submitYes">' + \
|
' <button type="submit" class="button" name="submitYes" ' + \
|
||||||
|
'accesskey="' + accessKeys['followButton'] + '">' + \
|
||||||
translate['Follow'] + '</button>\n'
|
translate['Follow'] + '</button>\n'
|
||||||
profileStr += \
|
profileStr += \
|
||||||
' <button type="submit" class="button" name="submitView">' + \
|
' <button type="submit" class="button" name="submitView" ' + \
|
||||||
|
'accesskey="' + accessKeys['viewButton'] + '">' + \
|
||||||
translate['View'] + '</button>\n'
|
translate['View'] + '</button>\n'
|
||||||
profileStr += ' </center>\n'
|
profileStr += ' </center>\n'
|
||||||
profileStr += ' </form>\n'
|
profileStr += ' </form>\n'
|
||||||
|
|
@ -331,14 +334,16 @@ def _getProfileHeader(baseDir: str, httpPrefix: str,
|
||||||
loginButton: str, avatarUrl: str,
|
loginButton: str, avatarUrl: str,
|
||||||
theme: str, movedTo: str,
|
theme: str, movedTo: str,
|
||||||
alsoKnownAs: [],
|
alsoKnownAs: [],
|
||||||
pinnedContent) -> str:
|
pinnedContent: str,
|
||||||
|
accessKeys: {}) -> str:
|
||||||
"""The header of the profile screen, containing background
|
"""The header of the profile screen, containing background
|
||||||
image and avatar
|
image and avatar
|
||||||
"""
|
"""
|
||||||
htmlStr = '\n\n <figure class="profileHeader">\n'
|
htmlStr = '\n\n <figure class="profileHeader">\n'
|
||||||
htmlStr += ' <a href="/users/' + \
|
htmlStr += ' <a href="/users/' + \
|
||||||
nickname + '/' + defaultTimeline + '" title="' + \
|
nickname + '/' + defaultTimeline + '" title="' + \
|
||||||
translate['Switch to timeline view'] + '">\n'
|
translate['Switch to timeline view'] + '" ' + \
|
||||||
|
'accesskey="' + accessKeys['menuTimeline'] + '">\n'
|
||||||
htmlStr += ' <img class="profileBackground" ' + \
|
htmlStr += ' <img class="profileBackground" ' + \
|
||||||
'alt="" ' + \
|
'alt="" ' + \
|
||||||
'src="/users/' + nickname + '/image_' + theme + '.png" /></a>\n'
|
'src="/users/' + nickname + '/image_' + theme + '.png" /></a>\n'
|
||||||
|
|
@ -411,14 +416,16 @@ def _getProfileHeaderAfterSearch(baseDir: str,
|
||||||
profileDescriptionShort: str,
|
profileDescriptionShort: str,
|
||||||
avatarUrl: str, imageUrl: str,
|
avatarUrl: str, imageUrl: str,
|
||||||
movedTo: str, actor: str,
|
movedTo: str, actor: str,
|
||||||
alsoKnownAs: []) -> str:
|
alsoKnownAs: [],
|
||||||
|
accessKeys: {}) -> str:
|
||||||
"""The header of a searched for handle, containing background
|
"""The header of a searched for handle, containing background
|
||||||
image and avatar
|
image and avatar
|
||||||
"""
|
"""
|
||||||
htmlStr = '\n\n <figure class="profileHeader">\n'
|
htmlStr = '\n\n <figure class="profileHeader">\n'
|
||||||
htmlStr += ' <a href="/users/' + \
|
htmlStr += ' <a href="/users/' + \
|
||||||
nickname + '/' + defaultTimeline + '" title="' + \
|
nickname + '/' + defaultTimeline + '" title="' + \
|
||||||
translate['Switch to timeline view'] + '">\n'
|
translate['Switch to timeline view'] + '" ' + \
|
||||||
|
'accesskey="' + accessKeys['menuTimeline'] + '">\n'
|
||||||
htmlStr += ' <img class="profileBackground" ' + \
|
htmlStr += ' <img class="profileBackground" ' + \
|
||||||
'alt="" ' + \
|
'alt="" ' + \
|
||||||
'src="' + imageUrl + '" /></a>\n'
|
'src="' + imageUrl + '" /></a>\n'
|
||||||
|
|
@ -489,7 +496,7 @@ def htmlProfile(rssIconAtTop: bool,
|
||||||
peertubeInstances: [],
|
peertubeInstances: [],
|
||||||
allowLocalNetworkAccess: bool,
|
allowLocalNetworkAccess: bool,
|
||||||
textModeBanner: str,
|
textModeBanner: str,
|
||||||
debug: bool,
|
debug: bool, accessKeys: {},
|
||||||
extraJson=None, pageNumber=None,
|
extraJson=None, pageNumber=None,
|
||||||
maxItemsPerPage=None) -> str:
|
maxItemsPerPage=None) -> str:
|
||||||
"""Show the profile page as html
|
"""Show the profile page as html
|
||||||
|
|
@ -509,7 +516,7 @@ def htmlProfile(rssIconAtTop: bool,
|
||||||
YTReplacementDomain,
|
YTReplacementDomain,
|
||||||
showPublishedDateOnly,
|
showPublishedDateOnly,
|
||||||
newswire, theme, extraJson,
|
newswire, theme, extraJson,
|
||||||
allowLocalNetworkAccess,
|
allowLocalNetworkAccess, accessKeys,
|
||||||
pageNumber, maxItemsPerPage)
|
pageNumber, maxItemsPerPage)
|
||||||
|
|
||||||
domain, port = getDomainFromActor(profileJson['id'])
|
domain, port = getDomainFromActor(profileJson['id'])
|
||||||
|
|
@ -723,7 +730,7 @@ def htmlProfile(rssIconAtTop: bool,
|
||||||
profileDescriptionShort,
|
profileDescriptionShort,
|
||||||
loginButton, avatarUrl, theme,
|
loginButton, avatarUrl, theme,
|
||||||
movedTo, alsoKnownAs,
|
movedTo, alsoKnownAs,
|
||||||
pinnedContent)
|
pinnedContent, accessKeys)
|
||||||
|
|
||||||
# keyboard navigation
|
# keyboard navigation
|
||||||
userPathStr = '/users/' + nickname
|
userPathStr = '/users/' + nickname
|
||||||
|
|
@ -755,7 +762,14 @@ def htmlProfile(rssIconAtTop: bool,
|
||||||
menuShares: userPathStr + '/shares#timeline',
|
menuShares: userPathStr + '/shares#timeline',
|
||||||
menuLogout: '/logout'
|
menuLogout: '/logout'
|
||||||
}
|
}
|
||||||
profileStr = htmlKeyboardNavigation(textModeBanner, navLinks)
|
navAccessKeys = {}
|
||||||
|
for variableName, key in accessKeys.items():
|
||||||
|
if not locals().get(variableName):
|
||||||
|
continue
|
||||||
|
navAccessKeys[locals()[variableName]] = key
|
||||||
|
|
||||||
|
profileStr = htmlKeyboardNavigation(textModeBanner,
|
||||||
|
navLinks, navAccessKeys)
|
||||||
|
|
||||||
profileStr += profileHeaderStr + donateSection
|
profileStr += profileHeaderStr + donateSection
|
||||||
profileStr += '<div class="container" id="buttonheader">\n'
|
profileStr += '<div class="container" id="buttonheader">\n'
|
||||||
|
|
@ -1184,6 +1198,14 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
|
||||||
with open(blockedFilename, 'r') as blockedfile:
|
with open(blockedFilename, 'r') as blockedfile:
|
||||||
blockedStr = blockedfile.read()
|
blockedStr = blockedfile.read()
|
||||||
|
|
||||||
|
dmAllowedInstancesStr = ''
|
||||||
|
dmAllowedInstancesFilename = \
|
||||||
|
baseDir + '/accounts/' + \
|
||||||
|
nickname + '@' + domain + '/dmAllowedInstances.txt'
|
||||||
|
if os.path.isfile(dmAllowedInstancesFilename):
|
||||||
|
with open(dmAllowedInstancesFilename, 'r') as dmAllowedInstancesFile:
|
||||||
|
dmAllowedInstancesStr = dmAllowedInstancesFile.read()
|
||||||
|
|
||||||
allowedInstancesStr = ''
|
allowedInstancesStr = ''
|
||||||
allowedInstancesFilename = \
|
allowedInstancesFilename = \
|
||||||
baseDir + '/accounts/' + \
|
baseDir + '/accounts/' + \
|
||||||
|
|
@ -1463,7 +1485,12 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
|
||||||
menuProfile: userPathStr,
|
menuProfile: userPathStr,
|
||||||
menuTimeline: userTimalineStr
|
menuTimeline: userTimalineStr
|
||||||
}
|
}
|
||||||
editProfileForm += htmlKeyboardNavigation(textModeBanner, navLinks)
|
navAccessKeys = {
|
||||||
|
menuProfile: 'p',
|
||||||
|
menuTimeline: 't'
|
||||||
|
}
|
||||||
|
editProfileForm += htmlKeyboardNavigation(textModeBanner,
|
||||||
|
navLinks, navAccessKeys)
|
||||||
|
|
||||||
# top banner
|
# top banner
|
||||||
editProfileForm += \
|
editProfileForm += \
|
||||||
|
|
@ -1740,6 +1767,18 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
|
||||||
' <textarea id="message" name="blocked" style="height:200px" ' + \
|
' <textarea id="message" name="blocked" style="height:200px" ' + \
|
||||||
'spellcheck="false">' + blockedStr + '</textarea>\n'
|
'spellcheck="false">' + blockedStr + '</textarea>\n'
|
||||||
|
|
||||||
|
editProfileForm += \
|
||||||
|
' <br><b><label class="labels">' + \
|
||||||
|
translate['Direct Message permitted instances'] + '</label></b>\n'
|
||||||
|
idx = 'Direct messages are always allowed from these instances.'
|
||||||
|
editProfileForm += \
|
||||||
|
' <br><label class="labels">' + \
|
||||||
|
translate[idx] + '</label>\n'
|
||||||
|
editProfileForm += \
|
||||||
|
' <textarea id="message" name="dmAllowedInstances" ' + \
|
||||||
|
'style="height:200px" spellcheck="false">' + \
|
||||||
|
dmAllowedInstancesStr + '</textarea>\n'
|
||||||
|
|
||||||
editProfileForm += \
|
editProfileForm += \
|
||||||
' <br><b><label class="labels">' + \
|
' <br><b><label class="labels">' + \
|
||||||
translate['Federation list'] + '</label></b>\n'
|
translate['Federation list'] + '</label></b>\n'
|
||||||
|
|
|
||||||
|
|
@ -319,7 +319,7 @@ def htmlSearchEmojiTextEntry(cssCache: {}, translate: {},
|
||||||
def htmlSearch(cssCache: {}, translate: {},
|
def htmlSearch(cssCache: {}, translate: {},
|
||||||
baseDir: str, path: str, domain: str,
|
baseDir: str, path: str, domain: str,
|
||||||
defaultTimeline: str, theme: str,
|
defaultTimeline: str, theme: str,
|
||||||
textModeBanner: str) -> str:
|
textModeBanner: str, accessKeys: {}) -> str:
|
||||||
"""Search called from the timeline icon
|
"""Search called from the timeline icon
|
||||||
"""
|
"""
|
||||||
actor = path.replace('/search', '')
|
actor = path.replace('/search', '')
|
||||||
|
|
@ -342,17 +342,19 @@ def htmlSearch(cssCache: {}, translate: {},
|
||||||
searchBannerFile, searchBannerFilename = \
|
searchBannerFile, searchBannerFilename = \
|
||||||
getSearchBannerFile(baseDir, searchNickname, domain, theme)
|
getSearchBannerFile(baseDir, searchNickname, domain, theme)
|
||||||
|
|
||||||
textModeBannerStr = htmlKeyboardNavigation(textModeBanner, {})
|
textModeBannerStr = htmlKeyboardNavigation(textModeBanner, {}, {})
|
||||||
if textModeBannerStr is None:
|
if textModeBannerStr is None:
|
||||||
textModeBannerStr = ''
|
textModeBannerStr = ''
|
||||||
|
|
||||||
if os.path.isfile(searchBannerFilename):
|
if os.path.isfile(searchBannerFilename):
|
||||||
|
timelineKey = accessKeys['menuTimeline']
|
||||||
usersPath = '/users/' + searchNickname
|
usersPath = '/users/' + searchNickname
|
||||||
followStr += \
|
followStr += \
|
||||||
'<header>\n' + textModeBannerStr + \
|
'<header>\n' + textModeBannerStr + \
|
||||||
'<a href="' + usersPath + '/' + defaultTimeline + '" title="' + \
|
'<a href="' + usersPath + '/' + defaultTimeline + '" title="' + \
|
||||||
translate['Switch to timeline view'] + '" alt="' + \
|
translate['Switch to timeline view'] + '" alt="' + \
|
||||||
translate['Switch to timeline view'] + '">\n'
|
translate['Switch to timeline view'] + '" ' + \
|
||||||
|
'accesskey="' + timelineKey + '">\n'
|
||||||
followStr += '<img loading="lazy" class="timeline-banner" src="' + \
|
followStr += '<img loading="lazy" class="timeline-banner" src="' + \
|
||||||
usersPath + '/' + searchBannerFile + '" alt="" /></a>\n' + \
|
usersPath + '/' + searchBannerFile + '" alt="" /></a>\n' + \
|
||||||
'</header>\n'
|
'</header>\n'
|
||||||
|
|
@ -370,8 +372,10 @@ def htmlSearch(cssCache: {}, translate: {},
|
||||||
followStr += \
|
followStr += \
|
||||||
' <input type="hidden" name="actor" value="' + actor + '">\n'
|
' <input type="hidden" name="actor" value="' + actor + '">\n'
|
||||||
followStr += ' <input type="text" name="searchtext" autofocus><br>\n'
|
followStr += ' <input type="text" name="searchtext" autofocus><br>\n'
|
||||||
|
submitKey = accessKeys['submitButton']
|
||||||
followStr += ' <button type="submit" class="button" ' + \
|
followStr += ' <button type="submit" class="button" ' + \
|
||||||
'name="submitSearch">' + translate['Submit'] + '</button>\n'
|
'name="submitSearch" accesskey="' + submitKey + '">' + \
|
||||||
|
translate['Submit'] + '</button>\n'
|
||||||
followStr += ' </form>\n'
|
followStr += ' </form>\n'
|
||||||
followStr += ' <p class="hashtagswarm">' + \
|
followStr += ' <p class="hashtagswarm">' + \
|
||||||
htmlHashTagSwarm(baseDir, actor, translate) + '</p>\n'
|
htmlHashTagSwarm(baseDir, actor, translate) + '</p>\n'
|
||||||
|
|
@ -404,6 +408,8 @@ def htmlSkillsSearch(actor: str,
|
||||||
continue
|
continue
|
||||||
if f.startswith('inbox@'):
|
if f.startswith('inbox@'):
|
||||||
continue
|
continue
|
||||||
|
elif f.startswith('news@'):
|
||||||
|
continue
|
||||||
actorFilename = os.path.join(subdir, f)
|
actorFilename = os.path.join(subdir, f)
|
||||||
actorJson = loadJson(actorFilename)
|
actorJson = loadJson(actorFilename)
|
||||||
if actorJson:
|
if actorJson:
|
||||||
|
|
@ -439,6 +445,8 @@ def htmlSkillsSearch(actor: str,
|
||||||
continue
|
continue
|
||||||
if f.startswith('inbox@'):
|
if f.startswith('inbox@'):
|
||||||
continue
|
continue
|
||||||
|
elif f.startswith('news@'):
|
||||||
|
continue
|
||||||
actorFilename = os.path.join(subdir, f)
|
actorFilename = os.path.join(subdir, f)
|
||||||
cachedActorJson = loadJson(actorFilename)
|
cachedActorJson = loadJson(actorFilename)
|
||||||
if cachedActorJson:
|
if cachedActorJson:
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,8 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
||||||
theme: str,
|
theme: str,
|
||||||
peertubeInstances: [],
|
peertubeInstances: [],
|
||||||
allowLocalNetworkAccess: bool,
|
allowLocalNetworkAccess: bool,
|
||||||
textModeBanner: str) -> str:
|
textModeBanner: str,
|
||||||
|
accessKeys: {}) -> str:
|
||||||
"""Show the timeline as html
|
"""Show the timeline as html
|
||||||
"""
|
"""
|
||||||
enableTimingLog = False
|
enableTimingLog = False
|
||||||
|
|
@ -268,7 +269,8 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
||||||
# show follow approvals icon
|
# show follow approvals icon
|
||||||
followApprovals = \
|
followApprovals = \
|
||||||
'<a href="' + usersPath + \
|
'<a href="' + usersPath + \
|
||||||
'/followers#buttonheader">' + \
|
'/followers#buttonheader" ' + \
|
||||||
|
'accesskey="' + accessKeys['followButton'] + '">' + \
|
||||||
'<img loading="lazy" ' + \
|
'<img loading="lazy" ' + \
|
||||||
'class="timelineicon" alt="' + \
|
'class="timelineicon" alt="' + \
|
||||||
translate['Approve follow requests'] + \
|
translate['Approve follow requests'] + \
|
||||||
|
|
@ -471,18 +473,23 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
||||||
menuCalendar: usersPath + '/calendar',
|
menuCalendar: usersPath + '/calendar',
|
||||||
menuDM: usersPath + '/dm#timelineposts',
|
menuDM: usersPath + '/dm#timelineposts',
|
||||||
menuReplies: usersPath + '/tlreplies#timelineposts',
|
menuReplies: usersPath + '/tlreplies#timelineposts',
|
||||||
menuOutbox: usersPath + '/inbox#timelineposts',
|
menuOutbox: usersPath + '/outbox#timelineposts',
|
||||||
menuBookmarks: usersPath + '/tlbookmarks#timelineposts',
|
menuBookmarks: usersPath + '/tlbookmarks#timelineposts',
|
||||||
menuShares: usersPath + '/tlshares#timelineposts',
|
menuShares: usersPath + '/tlshares#timelineposts',
|
||||||
menuBlogs: usersPath + '/tlblogs#timelineposts',
|
menuBlogs: usersPath + '/tlblogs#timelineposts',
|
||||||
# menuEvents: usersPath + '/tlevents#timelineposts',
|
|
||||||
menuNewswire: usersPath + '/newswiremobile',
|
menuNewswire: usersPath + '/newswiremobile',
|
||||||
menuLinks: usersPath + '/linksmobile'
|
menuLinks: usersPath + '/linksmobile'
|
||||||
}
|
}
|
||||||
|
navAccessKeys = {}
|
||||||
|
for variableName, key in accessKeys.items():
|
||||||
|
if not locals().get(variableName):
|
||||||
|
continue
|
||||||
|
navAccessKeys[locals()[variableName]] = key
|
||||||
if moderator:
|
if moderator:
|
||||||
navLinks[menuModeration] = usersPath + '/moderation#modtimeline'
|
navLinks[menuModeration] = usersPath + '/moderation#modtimeline'
|
||||||
tlStr += htmlKeyboardNavigation(textModeBanner, navLinks, None,
|
tlStr += htmlKeyboardNavigation(textModeBanner, navLinks, navAccessKeys,
|
||||||
usersPath, translate, followApprovals)
|
None, usersPath, translate,
|
||||||
|
followApprovals)
|
||||||
|
|
||||||
# banner and row of buttons
|
# banner and row of buttons
|
||||||
tlStr += \
|
tlStr += \
|
||||||
|
|
@ -509,7 +516,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
||||||
domain, timelineStartTime,
|
domain, timelineStartTime,
|
||||||
newCalendarEvent, calendarPath,
|
newCalendarEvent, calendarPath,
|
||||||
calendarImage, followApprovals,
|
calendarImage, followApprovals,
|
||||||
iconsAsButtons)
|
iconsAsButtons, accessKeys)
|
||||||
|
|
||||||
# start the timeline
|
# start the timeline
|
||||||
tlStr += '<table class="timeline">\n'
|
tlStr += '<table class="timeline">\n'
|
||||||
|
|
@ -528,7 +535,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
||||||
getLeftColumnContent(baseDir, nickname, domainFull,
|
getLeftColumnContent(baseDir, nickname, domainFull,
|
||||||
httpPrefix, translate,
|
httpPrefix, translate,
|
||||||
editor, False, None, rssIconAtTop,
|
editor, False, None, rssIconAtTop,
|
||||||
True, False, theme)
|
True, False, theme, accessKeys)
|
||||||
tlStr += ' <td valign="top" class="col-left" ' + \
|
tlStr += ' <td valign="top" class="col-left" ' + \
|
||||||
'id="links" tabindex="-1">' + \
|
'id="links" tabindex="-1">' + \
|
||||||
leftColumnStr + ' </td>\n'
|
leftColumnStr + ' </td>\n'
|
||||||
|
|
@ -549,7 +556,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
||||||
domain, timelineStartTime,
|
domain, timelineStartTime,
|
||||||
newCalendarEvent, calendarPath,
|
newCalendarEvent, calendarPath,
|
||||||
calendarImage, followApprovals,
|
calendarImage, followApprovals,
|
||||||
iconsAsButtons)
|
iconsAsButtons, accessKeys)
|
||||||
|
|
||||||
tlStr += ' <div id="timelineposts" class="timeline-posts">\n'
|
tlStr += ' <div id="timelineposts" class="timeline-posts">\n'
|
||||||
|
|
||||||
|
|
@ -654,7 +661,8 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
||||||
' <center>\n' + \
|
' <center>\n' + \
|
||||||
' <a href="' + usersPath + '/' + boxName + \
|
' <a href="' + usersPath + '/' + boxName + \
|
||||||
'?page=' + str(pageNumber - 1) + \
|
'?page=' + str(pageNumber - 1) + \
|
||||||
'"><img loading="lazy" class="pageicon" src="/' + \
|
'" accesskey="' + accessKeys['Page up'] + '">' + \
|
||||||
|
'<img loading="lazy" class="pageicon" src="/' + \
|
||||||
'icons/pageup.png" title="' + \
|
'icons/pageup.png" title="' + \
|
||||||
translate['Page up'] + '" alt="' + \
|
translate['Page up'] + '" alt="' + \
|
||||||
translate['Page up'] + '"></a>\n' + \
|
translate['Page up'] + '"></a>\n' + \
|
||||||
|
|
@ -747,7 +755,8 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
||||||
' <center>\n' + \
|
' <center>\n' + \
|
||||||
' <a href="' + usersPath + '/' + boxName + '?page=' + \
|
' <a href="' + usersPath + '/' + boxName + '?page=' + \
|
||||||
str(pageNumber + 1) + \
|
str(pageNumber + 1) + \
|
||||||
'"><img loading="lazy" class="pageicon" src="/' + \
|
'" accesskey="' + accessKeys['Page down'] + '">' + \
|
||||||
|
'<img loading="lazy" class="pageicon" src="/' + \
|
||||||
'icons/pagedown.png" title="' + \
|
'icons/pagedown.png" title="' + \
|
||||||
translate['Page down'] + '" alt="' + \
|
translate['Page down'] + '" alt="' + \
|
||||||
translate['Page down'] + '"></a>\n' + \
|
translate['Page down'] + '"></a>\n' + \
|
||||||
|
|
@ -771,7 +780,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
||||||
showPublishAsIcon,
|
showPublishAsIcon,
|
||||||
rssIconAtTop, publishButtonAtTop,
|
rssIconAtTop, publishButtonAtTop,
|
||||||
authorized, True, theme,
|
authorized, True, theme,
|
||||||
defaultTimeline)
|
defaultTimeline, accessKeys)
|
||||||
tlStr += ' <td valign="top" class="col-right" ' + \
|
tlStr += ' <td valign="top" class="col-right" ' + \
|
||||||
'id="newswire" tabindex="-1">' + \
|
'id="newswire" tabindex="-1">' + \
|
||||||
rightColumnStr + ' </td>\n'
|
rightColumnStr + ' </td>\n'
|
||||||
|
|
@ -894,7 +903,8 @@ def htmlShares(cssCache: {}, defaultTimeline: str,
|
||||||
authorized: bool, theme: str,
|
authorized: bool, theme: str,
|
||||||
peertubeInstances: [],
|
peertubeInstances: [],
|
||||||
allowLocalNetworkAccess: bool,
|
allowLocalNetworkAccess: bool,
|
||||||
textModeBanner: str) -> str:
|
textModeBanner: str,
|
||||||
|
accessKeys: {}) -> str:
|
||||||
"""Show the shares timeline as html
|
"""Show the shares timeline as html
|
||||||
"""
|
"""
|
||||||
manuallyApproveFollowers = \
|
manuallyApproveFollowers = \
|
||||||
|
|
@ -915,7 +925,8 @@ def htmlShares(cssCache: {}, defaultTimeline: str,
|
||||||
fullWidthTimelineButtonHeader,
|
fullWidthTimelineButtonHeader,
|
||||||
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
||||||
authorized, None, theme, peertubeInstances,
|
authorized, None, theme, peertubeInstances,
|
||||||
allowLocalNetworkAccess, textModeBanner)
|
allowLocalNetworkAccess, textModeBanner,
|
||||||
|
accessKeys)
|
||||||
|
|
||||||
|
|
||||||
def htmlInbox(cssCache: {}, defaultTimeline: str,
|
def htmlInbox(cssCache: {}, defaultTimeline: str,
|
||||||
|
|
@ -937,7 +948,8 @@ def htmlInbox(cssCache: {}, defaultTimeline: str,
|
||||||
authorized: bool, theme: str,
|
authorized: bool, theme: str,
|
||||||
peertubeInstances: [],
|
peertubeInstances: [],
|
||||||
allowLocalNetworkAccess: bool,
|
allowLocalNetworkAccess: bool,
|
||||||
textModeBanner: str) -> str:
|
textModeBanner: str,
|
||||||
|
accessKeys: {}) -> str:
|
||||||
"""Show the inbox as html
|
"""Show the inbox as html
|
||||||
"""
|
"""
|
||||||
manuallyApproveFollowers = \
|
manuallyApproveFollowers = \
|
||||||
|
|
@ -958,7 +970,8 @@ def htmlInbox(cssCache: {}, defaultTimeline: str,
|
||||||
fullWidthTimelineButtonHeader,
|
fullWidthTimelineButtonHeader,
|
||||||
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
||||||
authorized, None, theme, peertubeInstances,
|
authorized, None, theme, peertubeInstances,
|
||||||
allowLocalNetworkAccess, textModeBanner)
|
allowLocalNetworkAccess, textModeBanner,
|
||||||
|
accessKeys)
|
||||||
|
|
||||||
|
|
||||||
def htmlBookmarks(cssCache: {}, defaultTimeline: str,
|
def htmlBookmarks(cssCache: {}, defaultTimeline: str,
|
||||||
|
|
@ -980,7 +993,8 @@ def htmlBookmarks(cssCache: {}, defaultTimeline: str,
|
||||||
authorized: bool, theme: str,
|
authorized: bool, theme: str,
|
||||||
peertubeInstances: [],
|
peertubeInstances: [],
|
||||||
allowLocalNetworkAccess: bool,
|
allowLocalNetworkAccess: bool,
|
||||||
textModeBanner: str) -> str:
|
textModeBanner: str,
|
||||||
|
accessKeys: {}) -> str:
|
||||||
"""Show the bookmarks as html
|
"""Show the bookmarks as html
|
||||||
"""
|
"""
|
||||||
manuallyApproveFollowers = \
|
manuallyApproveFollowers = \
|
||||||
|
|
@ -1001,7 +1015,8 @@ def htmlBookmarks(cssCache: {}, defaultTimeline: str,
|
||||||
fullWidthTimelineButtonHeader,
|
fullWidthTimelineButtonHeader,
|
||||||
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
||||||
authorized, None, theme, peertubeInstances,
|
authorized, None, theme, peertubeInstances,
|
||||||
allowLocalNetworkAccess, textModeBanner)
|
allowLocalNetworkAccess, textModeBanner,
|
||||||
|
accessKeys)
|
||||||
|
|
||||||
|
|
||||||
def htmlEvents(cssCache: {}, defaultTimeline: str,
|
def htmlEvents(cssCache: {}, defaultTimeline: str,
|
||||||
|
|
@ -1023,7 +1038,8 @@ def htmlEvents(cssCache: {}, defaultTimeline: str,
|
||||||
authorized: bool, theme: str,
|
authorized: bool, theme: str,
|
||||||
peertubeInstances: [],
|
peertubeInstances: [],
|
||||||
allowLocalNetworkAccess: bool,
|
allowLocalNetworkAccess: bool,
|
||||||
textModeBanner: str) -> str:
|
textModeBanner: str,
|
||||||
|
accessKeys: {}) -> str:
|
||||||
"""Show the events as html
|
"""Show the events as html
|
||||||
"""
|
"""
|
||||||
manuallyApproveFollowers = \
|
manuallyApproveFollowers = \
|
||||||
|
|
@ -1044,7 +1060,8 @@ def htmlEvents(cssCache: {}, defaultTimeline: str,
|
||||||
fullWidthTimelineButtonHeader,
|
fullWidthTimelineButtonHeader,
|
||||||
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
||||||
authorized, None, theme, peertubeInstances,
|
authorized, None, theme, peertubeInstances,
|
||||||
allowLocalNetworkAccess, textModeBanner)
|
allowLocalNetworkAccess, textModeBanner,
|
||||||
|
accessKeys)
|
||||||
|
|
||||||
|
|
||||||
def htmlInboxDMs(cssCache: {}, defaultTimeline: str,
|
def htmlInboxDMs(cssCache: {}, defaultTimeline: str,
|
||||||
|
|
@ -1066,7 +1083,8 @@ def htmlInboxDMs(cssCache: {}, defaultTimeline: str,
|
||||||
authorized: bool, theme: str,
|
authorized: bool, theme: str,
|
||||||
peertubeInstances: [],
|
peertubeInstances: [],
|
||||||
allowLocalNetworkAccess: bool,
|
allowLocalNetworkAccess: bool,
|
||||||
textModeBanner: str) -> str:
|
textModeBanner: str,
|
||||||
|
accessKeys: {}) -> str:
|
||||||
"""Show the DM timeline as html
|
"""Show the DM timeline as html
|
||||||
"""
|
"""
|
||||||
return htmlTimeline(cssCache, defaultTimeline,
|
return htmlTimeline(cssCache, defaultTimeline,
|
||||||
|
|
@ -1082,7 +1100,8 @@ def htmlInboxDMs(cssCache: {}, defaultTimeline: str,
|
||||||
fullWidthTimelineButtonHeader,
|
fullWidthTimelineButtonHeader,
|
||||||
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
||||||
authorized, None, theme, peertubeInstances,
|
authorized, None, theme, peertubeInstances,
|
||||||
allowLocalNetworkAccess, textModeBanner)
|
allowLocalNetworkAccess, textModeBanner,
|
||||||
|
accessKeys)
|
||||||
|
|
||||||
|
|
||||||
def htmlInboxReplies(cssCache: {}, defaultTimeline: str,
|
def htmlInboxReplies(cssCache: {}, defaultTimeline: str,
|
||||||
|
|
@ -1104,7 +1123,8 @@ def htmlInboxReplies(cssCache: {}, defaultTimeline: str,
|
||||||
authorized: bool, theme: str,
|
authorized: bool, theme: str,
|
||||||
peertubeInstances: [],
|
peertubeInstances: [],
|
||||||
allowLocalNetworkAccess: bool,
|
allowLocalNetworkAccess: bool,
|
||||||
textModeBanner: str) -> str:
|
textModeBanner: str,
|
||||||
|
accessKeys: {}) -> str:
|
||||||
"""Show the replies timeline as html
|
"""Show the replies timeline as html
|
||||||
"""
|
"""
|
||||||
return htmlTimeline(cssCache, defaultTimeline,
|
return htmlTimeline(cssCache, defaultTimeline,
|
||||||
|
|
@ -1121,7 +1141,8 @@ def htmlInboxReplies(cssCache: {}, defaultTimeline: str,
|
||||||
fullWidthTimelineButtonHeader,
|
fullWidthTimelineButtonHeader,
|
||||||
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
||||||
authorized, None, theme, peertubeInstances,
|
authorized, None, theme, peertubeInstances,
|
||||||
allowLocalNetworkAccess, textModeBanner)
|
allowLocalNetworkAccess, textModeBanner,
|
||||||
|
accessKeys)
|
||||||
|
|
||||||
|
|
||||||
def htmlInboxMedia(cssCache: {}, defaultTimeline: str,
|
def htmlInboxMedia(cssCache: {}, defaultTimeline: str,
|
||||||
|
|
@ -1143,7 +1164,8 @@ def htmlInboxMedia(cssCache: {}, defaultTimeline: str,
|
||||||
authorized: bool, theme: str,
|
authorized: bool, theme: str,
|
||||||
peertubeInstances: [],
|
peertubeInstances: [],
|
||||||
allowLocalNetworkAccess: bool,
|
allowLocalNetworkAccess: bool,
|
||||||
textModeBanner: str) -> str:
|
textModeBanner: str,
|
||||||
|
accessKeys: {}) -> str:
|
||||||
"""Show the media timeline as html
|
"""Show the media timeline as html
|
||||||
"""
|
"""
|
||||||
return htmlTimeline(cssCache, defaultTimeline,
|
return htmlTimeline(cssCache, defaultTimeline,
|
||||||
|
|
@ -1160,7 +1182,8 @@ def htmlInboxMedia(cssCache: {}, defaultTimeline: str,
|
||||||
fullWidthTimelineButtonHeader,
|
fullWidthTimelineButtonHeader,
|
||||||
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
||||||
authorized, None, theme, peertubeInstances,
|
authorized, None, theme, peertubeInstances,
|
||||||
allowLocalNetworkAccess, textModeBanner)
|
allowLocalNetworkAccess, textModeBanner,
|
||||||
|
accessKeys)
|
||||||
|
|
||||||
|
|
||||||
def htmlInboxBlogs(cssCache: {}, defaultTimeline: str,
|
def htmlInboxBlogs(cssCache: {}, defaultTimeline: str,
|
||||||
|
|
@ -1182,7 +1205,8 @@ def htmlInboxBlogs(cssCache: {}, defaultTimeline: str,
|
||||||
authorized: bool, theme: str,
|
authorized: bool, theme: str,
|
||||||
peertubeInstances: [],
|
peertubeInstances: [],
|
||||||
allowLocalNetworkAccess: bool,
|
allowLocalNetworkAccess: bool,
|
||||||
textModeBanner: str) -> str:
|
textModeBanner: str,
|
||||||
|
accessKeys: {}) -> str:
|
||||||
"""Show the blogs timeline as html
|
"""Show the blogs timeline as html
|
||||||
"""
|
"""
|
||||||
return htmlTimeline(cssCache, defaultTimeline,
|
return htmlTimeline(cssCache, defaultTimeline,
|
||||||
|
|
@ -1199,7 +1223,8 @@ def htmlInboxBlogs(cssCache: {}, defaultTimeline: str,
|
||||||
fullWidthTimelineButtonHeader,
|
fullWidthTimelineButtonHeader,
|
||||||
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
||||||
authorized, None, theme, peertubeInstances,
|
authorized, None, theme, peertubeInstances,
|
||||||
allowLocalNetworkAccess, textModeBanner)
|
allowLocalNetworkAccess, textModeBanner,
|
||||||
|
accessKeys)
|
||||||
|
|
||||||
|
|
||||||
def htmlInboxFeatures(cssCache: {}, defaultTimeline: str,
|
def htmlInboxFeatures(cssCache: {}, defaultTimeline: str,
|
||||||
|
|
@ -1222,7 +1247,8 @@ def htmlInboxFeatures(cssCache: {}, defaultTimeline: str,
|
||||||
theme: str,
|
theme: str,
|
||||||
peertubeInstances: [],
|
peertubeInstances: [],
|
||||||
allowLocalNetworkAccess: bool,
|
allowLocalNetworkAccess: bool,
|
||||||
textModeBanner: str) -> str:
|
textModeBanner: str,
|
||||||
|
accessKeys: {}) -> str:
|
||||||
"""Show the features timeline as html
|
"""Show the features timeline as html
|
||||||
"""
|
"""
|
||||||
return htmlTimeline(cssCache, defaultTimeline,
|
return htmlTimeline(cssCache, defaultTimeline,
|
||||||
|
|
@ -1239,7 +1265,8 @@ def htmlInboxFeatures(cssCache: {}, defaultTimeline: str,
|
||||||
fullWidthTimelineButtonHeader,
|
fullWidthTimelineButtonHeader,
|
||||||
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
||||||
authorized, None, theme, peertubeInstances,
|
authorized, None, theme, peertubeInstances,
|
||||||
allowLocalNetworkAccess, textModeBanner)
|
allowLocalNetworkAccess, textModeBanner,
|
||||||
|
accessKeys)
|
||||||
|
|
||||||
|
|
||||||
def htmlInboxNews(cssCache: {}, defaultTimeline: str,
|
def htmlInboxNews(cssCache: {}, defaultTimeline: str,
|
||||||
|
|
@ -1261,7 +1288,8 @@ def htmlInboxNews(cssCache: {}, defaultTimeline: str,
|
||||||
authorized: bool, theme: str,
|
authorized: bool, theme: str,
|
||||||
peertubeInstances: [],
|
peertubeInstances: [],
|
||||||
allowLocalNetworkAccess: bool,
|
allowLocalNetworkAccess: bool,
|
||||||
textModeBanner: str) -> str:
|
textModeBanner: str,
|
||||||
|
accessKeys: {}) -> str:
|
||||||
"""Show the news timeline as html
|
"""Show the news timeline as html
|
||||||
"""
|
"""
|
||||||
return htmlTimeline(cssCache, defaultTimeline,
|
return htmlTimeline(cssCache, defaultTimeline,
|
||||||
|
|
@ -1278,7 +1306,8 @@ def htmlInboxNews(cssCache: {}, defaultTimeline: str,
|
||||||
fullWidthTimelineButtonHeader,
|
fullWidthTimelineButtonHeader,
|
||||||
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
||||||
authorized, None, theme, peertubeInstances,
|
authorized, None, theme, peertubeInstances,
|
||||||
allowLocalNetworkAccess, textModeBanner)
|
allowLocalNetworkAccess, textModeBanner,
|
||||||
|
accessKeys)
|
||||||
|
|
||||||
|
|
||||||
def htmlOutbox(cssCache: {}, defaultTimeline: str,
|
def htmlOutbox(cssCache: {}, defaultTimeline: str,
|
||||||
|
|
@ -1300,7 +1329,8 @@ def htmlOutbox(cssCache: {}, defaultTimeline: str,
|
||||||
authorized: bool, theme: str,
|
authorized: bool, theme: str,
|
||||||
peertubeInstances: [],
|
peertubeInstances: [],
|
||||||
allowLocalNetworkAccess: bool,
|
allowLocalNetworkAccess: bool,
|
||||||
textModeBanner: str) -> str:
|
textModeBanner: str,
|
||||||
|
accessKeys: {}) -> str:
|
||||||
"""Show the Outbox as html
|
"""Show the Outbox as html
|
||||||
"""
|
"""
|
||||||
manuallyApproveFollowers = \
|
manuallyApproveFollowers = \
|
||||||
|
|
@ -1318,4 +1348,5 @@ def htmlOutbox(cssCache: {}, defaultTimeline: str,
|
||||||
showPublishAsIcon, fullWidthTimelineButtonHeader,
|
showPublishAsIcon, fullWidthTimelineButtonHeader,
|
||||||
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
|
||||||
authorized, None, theme, peertubeInstances,
|
authorized, None, theme, peertubeInstances,
|
||||||
allowLocalNetworkAccess, textModeBanner)
|
allowLocalNetworkAccess, textModeBanner,
|
||||||
|
accessKeys)
|
||||||
|
|
|
||||||
|
|
@ -1114,7 +1114,7 @@ def htmlHideFromScreenReader(htmlStr: str) -> str:
|
||||||
return '<span aria-hidden="true">' + htmlStr + '</span>'
|
return '<span aria-hidden="true">' + htmlStr + '</span>'
|
||||||
|
|
||||||
|
|
||||||
def htmlKeyboardNavigation(banner: str, links: {},
|
def htmlKeyboardNavigation(banner: str, links: {}, accessKeys: {},
|
||||||
subHeading=None,
|
subHeading=None,
|
||||||
usersPath=None, translate=None,
|
usersPath=None, translate=None,
|
||||||
followApprovals=False) -> str:
|
followApprovals=False) -> str:
|
||||||
|
|
@ -1138,8 +1138,12 @@ def htmlKeyboardNavigation(banner: str, links: {},
|
||||||
|
|
||||||
# show the list of links
|
# show the list of links
|
||||||
for title, url in links.items():
|
for title, url in links.items():
|
||||||
|
accessKeyStr = ''
|
||||||
|
if accessKeys.get(title):
|
||||||
|
accessKeyStr = 'accesskey="' + accessKeys[title] + '"'
|
||||||
|
|
||||||
htmlStr += '<li><label class="transparent">' + \
|
htmlStr += '<li><label class="transparent">' + \
|
||||||
'<a href="' + str(url) + '">' + \
|
'<a href="' + str(url) + '" ' + accessKeyStr + '>' + \
|
||||||
str(title) + '</a></label></li>\n'
|
str(title) + '</a></label></li>\n'
|
||||||
htmlStr += '</ul></div>\n'
|
htmlStr += '</ul></div>\n'
|
||||||
return htmlStr
|
return htmlStr
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,8 @@ def htmlWelcomeProfile(baseDir: str, nickname: str, domain: str,
|
||||||
|
|
||||||
bioStr = \
|
bioStr = \
|
||||||
actorJson['summary'].replace('<p>', '').replace('</p>', '')
|
actorJson['summary'].replace('<p>', '').replace('</p>', '')
|
||||||
|
if not bioStr:
|
||||||
|
bioStr = translate['Your bio']
|
||||||
profileForm += ' <label class="labels">' + \
|
profileForm += ' <label class="labels">' + \
|
||||||
translate['Your bio'] + '</label><br>\n'
|
translate['Your bio'] + '</label><br>\n'
|
||||||
profileForm += ' <textarea id="message" name="bio" ' + \
|
profileForm += ' <textarea id="message" name="bio" ' + \
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue