diff --git a/daemon.py b/daemon.py index 0c70a77fb..675a205de 100644 --- a/daemon.py +++ b/daemon.py @@ -230,6 +230,7 @@ from media import removeMetaData from cache import storePersonInCache from cache import getPersonFromCache from httpsig import verifyPostHeaders +from theme import getTextModeBanner from theme import setNewsAvatar from theme import setTheme from theme import getTheme @@ -2078,7 +2079,8 @@ class PubServer(BaseHTTPRequestHandler): domainFull, self.server.defaultTimeline, self.server.newswire, - self.server.themeName).encode('utf-8') + self.server.themeName, + True).encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, cookie, callingDomain) @@ -2176,7 +2178,8 @@ class PubServer(BaseHTTPRequestHandler): domainFull, self.server.defaultTimeline, self.server.newswire, - self.server.themeName).encode('utf-8') + self.server.themeName, + True).encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, cookie, callingDomain) @@ -4169,6 +4172,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.themeName = fields['themeDropdown'] setTheme(baseDir, self.server.themeName, domain, allowLocalNetworkAccess) + self.server.textModeBanner = \ + getTextModeBanner(self.server.baseDir) self.server.iconsCache = {} self.server.fontsCache = {} self.server.showPublishAsIcon = \ @@ -4618,6 +4623,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.themeName = currTheme setTheme(baseDir, currTheme, domain, self.server.allowLocalNetworkAccess) + self.server.textModeBanner = \ + getTextModeBanner(self.server.baseDir) self.server.iconsCache = {} self.server.fontsCache = {} self.server.showPublishAsIcon = \ @@ -7023,6 +7030,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.dormantMonths, self.server.peertubeInstances, self.server.allowLocalNetworkAccess, + self.server.textModeBanner, actorJson['roles'], None, None) msg = msg.encode('utf-8') @@ -7110,6 +7118,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.dormantMonths, self.server.peertubeInstances, allowLocalNetworkAccess, + self.server.textModeBanner, actorJson['skills'], None, None) msg = msg.encode('utf-8') @@ -7501,7 +7510,8 @@ class PubServer(BaseHTTPRequestHandler): authorized, self.server.themeName, self.server.peertubeInstances, - self.server.allowLocalNetworkAccess) + self.server.allowLocalNetworkAccess, + self.server.textModeBanner) if GETstartTime: self._benchmarkGETtimings(GETstartTime, GETtimings, 'show status done', @@ -7629,7 +7639,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.publishButtonAtTop, authorized, self.server.themeName, self.server.peertubeInstances, - self.server.allowLocalNetworkAccess) + self.server.allowLocalNetworkAccess, + self.server.textModeBanner) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -7750,7 +7761,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.publishButtonAtTop, authorized, self.server.themeName, self.server.peertubeInstances, - self.server.allowLocalNetworkAccess) + self.server.allowLocalNetworkAccess, + self.server.textModeBanner) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -7872,7 +7884,8 @@ class PubServer(BaseHTTPRequestHandler): authorized, self.server.themeName, self.server.peertubeInstances, - self.server.allowLocalNetworkAccess) + self.server.allowLocalNetworkAccess, + self.server.textModeBanner) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -7994,7 +8007,8 @@ class PubServer(BaseHTTPRequestHandler): authorized, self.server.themeName, self.server.peertubeInstances, - self.server.allowLocalNetworkAccess) + self.server.allowLocalNetworkAccess, + self.server.textModeBanner) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8125,7 +8139,8 @@ class PubServer(BaseHTTPRequestHandler): authorized, self.server.themeName, self.server.peertubeInstances, - self.server.allowLocalNetworkAccess) + self.server.allowLocalNetworkAccess, + self.server.textModeBanner) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8252,7 +8267,8 @@ class PubServer(BaseHTTPRequestHandler): authorized, self.server.themeName, self.server.peertubeInstances, - self.server.allowLocalNetworkAccess) + self.server.allowLocalNetworkAccess, + self.server.textModeBanner) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8340,7 +8356,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.publishButtonAtTop, authorized, self.server.themeName, self.server.peertubeInstances, - self.server.allowLocalNetworkAccess) + self.server.allowLocalNetworkAccess, + self.server.textModeBanner) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8445,7 +8462,8 @@ class PubServer(BaseHTTPRequestHandler): authorized, self.server.themeName, self.server.peertubeInstances, - self.server.allowLocalNetworkAccess) + self.server.allowLocalNetworkAccess, + self.server.textModeBanner) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8570,7 +8588,8 @@ class PubServer(BaseHTTPRequestHandler): authorized, self.server.themeName, self.server.peertubeInstances, - self.server.allowLocalNetworkAccess) + self.server.allowLocalNetworkAccess, + self.server.textModeBanner) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8687,7 +8706,8 @@ class PubServer(BaseHTTPRequestHandler): authorized, self.server.themeName, self.server.peertubeInstances, - self.server.allowLocalNetworkAccess) + self.server.allowLocalNetworkAccess, + self.server.textModeBanner) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8794,7 +8814,8 @@ class PubServer(BaseHTTPRequestHandler): authorized, moderationActionStr, self.server.themeName, self.server.peertubeInstances, - self.server.allowLocalNetworkAccess) + self.server.allowLocalNetworkAccess, + self.server.textModeBanner) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8895,6 +8916,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.dormantMonths, self.server.peertubeInstances, self.server.allowLocalNetworkAccess, + self.server.textModeBanner, shares, pageNumber, sharesPerPage) msg = msg.encode('utf-8') @@ -8992,6 +9014,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.dormantMonths, self.server.peertubeInstances, self.server.allowLocalNetworkAccess, + self.server.textModeBanner, following, pageNumber, followsPerPage).encode('utf-8') @@ -9089,6 +9112,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.dormantMonths, self.server.peertubeInstances, self.server.allowLocalNetworkAccess, + self.server.textModeBanner, followers, pageNumber, followsPerPage).encode('utf-8') @@ -9209,6 +9233,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.dormantMonths, self.server.peertubeInstances, self.server.allowLocalNetworkAccess, + self.server.textModeBanner, None, None).encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -9711,7 +9736,8 @@ class PubServer(BaseHTTPRequestHandler): inReplyToUrl: str, replyToList: [], shareDescription: str, replyPageNumber: int, domain: str, domainFull: str, - GETstartTime, GETtimings: {}, cookie) -> bool: + GETstartTime, GETtimings: {}, cookie, + noDropDown: bool) -> bool: """Shows the new post screen """ isNewPostEndpoint = False @@ -9740,7 +9766,8 @@ class PubServer(BaseHTTPRequestHandler): domainFull, self.server.defaultTimeline, self.server.newswire, - self.server.themeName).encode('utf-8') + self.server.themeName, + noDropDown).encode('utf-8') if not msg: print('Error replying to ' + inReplyToUrl) self._404() @@ -9773,7 +9800,8 @@ class PubServer(BaseHTTPRequestHandler): httpPrefix, self.server.defaultTimeline, self.server.themeName, - peertubeInstances).encode('utf-8') + peertubeInstances, + self.server.textModeBanner).encode('utf-8') if msg: msglen = len(msg) self._set_headers('text/html', msglen, @@ -9983,6 +10011,12 @@ class PubServer(BaseHTTPRequestHandler): if self.path.startswith('/@'): self.path = self.path.replace('/@', '/users/') + # turn off dropdowns on new post screen + noDropDown = False + if self.path.endswith('?nodropdown'): + noDropDown = True + self.path = self.path.replace('?nodropdown', '') + # redirect music to #nowplaying list if self.path == '/music' or self.path == '/nowplaying': self.path = '/tags/nowplaying' @@ -11009,7 +11043,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.baseDir, self.path, self.server.domain, self.server.defaultTimeline, - self.server.themeName).encode('utf-8') + self.server.themeName, + self.server.textModeBanner).encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, cookie, callingDomain) self._write(msg) @@ -11556,7 +11591,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.domain, self.server.domainFull, GETstartTime, GETtimings, - cookie): + cookie, noDropDown): return self._benchmarkGETtimings(GETstartTime, GETtimings, @@ -13850,6 +13885,9 @@ def runDaemon(verifyAllSignatures: bool, print('ERROR: HTTP server failed to start. ' + str(e)) return False + # ASCII/ANSI text banner used in shell browsers, such as Lynx + httpd.textModeBanner = getTextModeBanner(baseDir) + httpd.unitTest = unitTest httpd.allowLocalNetworkAccess = allowLocalNetworkAccess if unitTest: diff --git a/epicyon-login.css b/epicyon-login.css index 6e8db72d5..30032f976 100644 --- a/epicyon-login.css +++ b/epicyon-login.css @@ -94,6 +94,14 @@ form { border-radius: var(--form-border-radius); } +.transparent { + color: transparent; + background: transparent; + font-size: 0px; + line-height: 0px; + height: 0px; +} + input[type=text], input[type=password] { width: 100%; padding: 12px 20px; diff --git a/epicyon-profile.css b/epicyon-profile.css index 1fa683db6..282aed28f 100644 --- a/epicyon-profile.css +++ b/epicyon-profile.css @@ -702,6 +702,15 @@ input[type=number] { height: 0px; } +.transparent hr { + border: 0; + color: transparent; + background: transparent; + font-size: 0px; + line-height: 0px; + height: 0px; +} + .labelsright { float: right; font-size: var(--font-size); @@ -1145,7 +1154,7 @@ div.container { filter: brightness(var(--icon-brightness-change)); } .col-right img.rightColEdit { - float: right; + float: right; background: transparent; width: var(--column-right-icon-size); } diff --git a/epicyon-search.css b/epicyon-search.css index 9f61bcd1f..c2078c108 100644 --- a/epicyon-search.css +++ b/epicyon-search.css @@ -102,6 +102,14 @@ a:focus { border: 2px solid var(--focus-color); } +.transparent { + color: transparent; + background: transparent; + font-size: 0px; + line-height: 0px; + height: 0px; +} + .cw { font-style: var(--cw-style); color: var(--cw-color); diff --git a/img/logo.txt b/img/logo.txt new file mode 100644 index 000000000..388fef656 --- /dev/null +++ b/img/logo.txt @@ -0,0 +1,8 @@ + 8888888888 8888888b. 8888888 .d8888b. Y88b d88P .d88888b. 888b 888 + 888 888 Y88b 888 d88P Y88b Y88b d88P d88P" "Y88b 8888b 888 + 888 888 888 888 888 888 Y88o88P 888 888 88888b 888 + 8888888 888 d88P 888 888 Y888P 888 888 888Y88b 888 + 888 8888888P" 888 888 888 888 888 888 Y88b888 + 888 888 888 888 888 888 888 888 888 Y88888 + 888 888 888 Y88b d88P 888 Y88b. .d88P 888 Y8888 + 8888888888 888 8888888 "Y8888P" 888 "Y88888P" 888 Y888 diff --git a/setup.cfg b/setup.cfg index 3f3e838ff..6b3bd5005 100644 --- a/setup.cfg +++ b/setup.cfg @@ -25,11 +25,10 @@ scripts = deploy/i2p deploy/onion install_requires = - crypto >= 1.4.1, < 2 idna >= 2.5, < 3 numpy >= 1.20.0, < 2 pillow >= 8.1.0, < 9 - cryptography + cryptography >= 3.3.1, < 4 pyqrcode >= 1.2.1, < 2 python-dateutil >= 2.8.1, < 3 requests >= 2.25.1, < 3 diff --git a/theme.py b/theme.py index e641b8829..9a27ec6e6 100644 --- a/theme.py +++ b/theme.py @@ -15,6 +15,8 @@ from content import dangerousCSS def _getThemeFiles() -> []: + """Gets the list of theme style sheets + """ return ('epicyon.css', 'login.css', 'follow.css', 'suspended.css', 'calendar.css', 'blog.css', 'options.css', 'search.css', 'links.css') @@ -39,6 +41,8 @@ def getThemesList(baseDir: str) -> []: def _setThemeInConfig(baseDir: str, name: str) -> bool: + """Sets the theme with the given name within config.json + """ configFilename = baseDir + '/config.json' if not os.path.isfile(configFilename): return False @@ -118,6 +122,8 @@ def _setFullWidthTimelineButtonHeader(baseDir: str, fullWidth: bool) -> bool: def getTheme(baseDir: str) -> str: + """Gets the current theme name from config.json + """ configFilename = baseDir + '/config.json' if os.path.isfile(configFilename): configJson = loadJson(configFilename, 0) @@ -128,6 +134,8 @@ def getTheme(baseDir: str) -> str: def _removeTheme(baseDir: str): + """Removes the current theme style sheets + """ themeFiles = _getThemeFiles() for filename in themeFiles: if os.path.isfile(baseDir + '/' + filename): @@ -422,6 +430,63 @@ def _setThemeFonts(baseDir: str, themeName: str) -> None: break +def getTextModeBanner(baseDir: str) -> str: + """Returns the banner used for shell browsers, like Lynx + """ + textModeBannerFilename = baseDir + '/accounts/banner.txt' + if os.path.isfile(textModeBannerFilename): + with open(textModeBannerFilename, 'r') as fp: + bannerStr = fp.read() + if bannerStr: + return bannerStr.replace('\n', '
') + return None + + +def getTextModeLogo(baseDir: str) -> str: + """Returns the login screen logo used for shell browsers, like Lynx + """ + textModeLogoFilename = baseDir + '/accounts/logo.txt' + if not os.path.isfile(textModeLogoFilename): + textModeLogoFilename = baseDir + '/img/logo.txt' + + with open(textModeLogoFilename, 'r') as fp: + logoStr = fp.read() + if logoStr: + return logoStr.replace('\n', '
') + return None + + +def _setTextModeTheme(baseDir: str, name: str) -> None: + # set the text mode logo which appears on the login screen + # in browsers such as Lynx + textModeLogoFilename = \ + baseDir + '/theme/' + name + '/logo.txt' + if os.path.isfile(textModeLogoFilename): + try: + copyfile(textModeLogoFilename, + baseDir + '/accounts/logo.txt') + except BaseException: + pass + else: + try: + copyfile(baseDir + '/img/logo.txt', + baseDir + '/accounts/logo.txt') + except BaseException: + pass + + # set the text mode banner which appears in browsers such as Lynx + textModeBannerFilename = \ + baseDir + '/theme/' + name + '/banner.txt' + if os.path.isfile(baseDir + '/accounts/banner.txt'): + os.remove(baseDir + '/accounts/banner.txt') + if os.path.isfile(textModeBannerFilename): + try: + copyfile(textModeBannerFilename, + baseDir + '/accounts/banner.txt') + except BaseException: + pass + + def _setThemeImages(baseDir: str, name: str) -> None: """Changes the profile background image and banner to the defaults @@ -439,6 +504,8 @@ def _setThemeImages(baseDir: str, name: str) -> None: rightColImageFilename = \ baseDir + '/theme/' + themeNameLower + '/right_col_image.png' + _setTextModeTheme(baseDir, themeNameLower) + backgroundNames = ('login', 'shares', 'delete', 'follow', 'options', 'block', 'search', 'calendar') extensions = getImageExtensions() @@ -554,6 +621,8 @@ def setNewsAvatar(baseDir: str, name: str, def setTheme(baseDir: str, name: str, domain: str, allowLocalNetworkAccess: bool) -> bool: + """Sets the theme with the given name as the current theme + """ result = False prevThemeName = getTheme(baseDir) diff --git a/theme/blue/banner.txt b/theme/blue/banner.txt new file mode 100644 index 000000000..db5cf9014 --- /dev/null +++ b/theme/blue/banner.txt @@ -0,0 +1,10 @@ + 88888888888 88 + 88 "" + 88 + 88aaaaa 8b,dPPYba, 88 ,adPPYba, 8b d8 ,adPPYba, 8b,dPPYba, + 88""""" 88P' "8a 88 a8" "" `8b d8' a8" "8a 88P' `"8a + 88 88 d8 88 8b `8b d8' 8b d8 88 88 + 88 88b, ,a8" 88 "8a, ,aa `8b,d8' "8a, ,a8" 88 88 + 88888888888 88`YbbdP"' 88 `"Ybbd8"' Y88' `"YbbdP"' 88 88 + 88 d8' + 88 d8' diff --git a/theme/blue/logo.txt b/theme/blue/logo.txt new file mode 100644 index 000000000..db5cf9014 --- /dev/null +++ b/theme/blue/logo.txt @@ -0,0 +1,10 @@ + 88888888888 88 + 88 "" + 88 + 88aaaaa 8b,dPPYba, 88 ,adPPYba, 8b d8 ,adPPYba, 8b,dPPYba, + 88""""" 88P' "8a 88 a8" "" `8b d8' a8" "8a 88P' `"8a + 88 88 d8 88 8b `8b d8' 8b d8 88 88 + 88 88b, ,a8" 88 "8a, ,aa `8b,d8' "8a, ,a8" 88 88 + 88888888888 88`YbbdP"' 88 `"Ybbd8"' Y88' `"YbbdP"' 88 88 + 88 d8' + 88 d8' diff --git a/theme/debian/banner.txt b/theme/debian/banner.txt new file mode 100644 index 000000000..2a43d236e --- /dev/null +++ b/theme/debian/banner.txt @@ -0,0 +1,11 @@ + _, _, ,'`. + `$$' `$$' `. ,' E P I C Y O N + $$ $$ `' + $$ $$ _, _ + ,d$$$g$$ ,d$$$b. $$,d$$$b.`$$' g$$$$$b.`$$,d$$b. + ,$P' `$$ ,$P' `Y$. $$$' `$$ $$ "' `$$ $$$' `$$ + $$' $$ $$' `$$ $$' $$ $$ ,ggggg$$ $$' $$ + $$ $$ $$ggggg$$ $$ $$ $$ ,$P" $$ $$ $$ + $$ ,$$ $$. $$ ,$P $$ $$' ,$$ $$ $$ + `$g. ,$$$ `$$._ _., $$ _,g$P' $$ `$b. ,$$$ $$ $$ + `Y$$P'$$. `Y$$$$P',$$$$P"' ,$$. `Y$$P'$$.$$. ,$$. diff --git a/theme/debian/logo.txt b/theme/debian/logo.txt new file mode 100644 index 000000000..cc624862a --- /dev/null +++ b/theme/debian/logo.txt @@ -0,0 +1,14 @@ + _,met$$$$$gg. + ,g$$$$$$$$$$$$$$$P. + ,g$$P"" """Y$$.". + ,$$P' `$$$. + ,$$P ,ggs. `$$b: + `d$$' ,$P"' . $$$ + $$P d$' , $$P + $$: $$. - ,d$$' + $$; Y$b._ _,d$P' + Y$$. `.`"Y$$$$P"' + `$$b "-.__ + `Y$$b + `$$. E P I C Y O N + `$. diff --git a/theme/default/banner.txt b/theme/default/banner.txt new file mode 100644 index 000000000..ffe9419c0 --- /dev/null +++ b/theme/default/banner.txt @@ -0,0 +1,8 @@ + __ + , ," e`--o + (( ( | __,' + \\~-------' \_;/ + ( / + /) .______. ) + (( ( (( ( + ``-' ``-' diff --git a/theme/default/logo.txt b/theme/default/logo.txt new file mode 100644 index 000000000..388fef656 --- /dev/null +++ b/theme/default/logo.txt @@ -0,0 +1,8 @@ + 8888888888 8888888b. 8888888 .d8888b. Y88b d88P .d88888b. 888b 888 + 888 888 Y88b 888 d88P Y88b Y88b d88P d88P" "Y88b 8888b 888 + 888 888 888 888 888 888 Y88o88P 888 888 88888b 888 + 8888888 888 d88P 888 888 Y888P 888 888 888Y88b 888 + 888 8888888P" 888 888 888 888 888 888 Y88b888 + 888 888 888 888 888 888 888 888 888 Y88888 + 888 888 888 Y88b d88P 888 Y88b. .d88P 888 Y8888 + 8888888888 888 8888888 "Y8888P" 888 "Y88888P" 888 Y888 diff --git a/theme/hacker/banner.txt b/theme/hacker/banner.txt new file mode 100644 index 000000000..db5cf9014 --- /dev/null +++ b/theme/hacker/banner.txt @@ -0,0 +1,10 @@ + 88888888888 88 + 88 "" + 88 + 88aaaaa 8b,dPPYba, 88 ,adPPYba, 8b d8 ,adPPYba, 8b,dPPYba, + 88""""" 88P' "8a 88 a8" "" `8b d8' a8" "8a 88P' `"8a + 88 88 d8 88 8b `8b d8' 8b d8 88 88 + 88 88b, ,a8" 88 "8a, ,aa `8b,d8' "8a, ,a8" 88 88 + 88888888888 88`YbbdP"' 88 `"Ybbd8"' Y88' `"YbbdP"' 88 88 + 88 d8' + 88 d8' diff --git a/theme/hacker/logo.txt b/theme/hacker/logo.txt new file mode 100644 index 000000000..db5cf9014 --- /dev/null +++ b/theme/hacker/logo.txt @@ -0,0 +1,10 @@ + 88888888888 88 + 88 "" + 88 + 88aaaaa 8b,dPPYba, 88 ,adPPYba, 8b d8 ,adPPYba, 8b,dPPYba, + 88""""" 88P' "8a 88 a8" "" `8b d8' a8" "8a 88P' `"8a + 88 88 d8 88 8b `8b d8' 8b d8 88 88 + 88 88b, ,a8" 88 "8a, ,aa `8b,d8' "8a, ,a8" 88 88 + 88888888888 88`YbbdP"' 88 `"Ybbd8"' Y88' `"YbbdP"' 88 88 + 88 d8' + 88 d8' diff --git a/theme/henge/banner.txt b/theme/henge/banner.txt new file mode 100644 index 000000000..93c88b2f1 --- /dev/null +++ b/theme/henge/banner.txt @@ -0,0 +1,7 @@ + ____ _________ __ _____ ___ ____ + / _]| \ | / ]| | | / \ | \ + | [_ | o ) | / / | | || || _ | + | _]| _/| |/ / | ~ || O || | | + | [_ | | | / \_ |___, || || | | + | || | | \ || || || | | + |_____||__| |____\____||____/ \___/ |__|__| diff --git a/theme/henge/logo.txt b/theme/henge/logo.txt new file mode 100644 index 000000000..93c88b2f1 --- /dev/null +++ b/theme/henge/logo.txt @@ -0,0 +1,7 @@ + ____ _________ __ _____ ___ ____ + / _]| \ | / ]| | | / \ | \ + | [_ | o ) | / / | | || || _ | + | _]| _/| |/ / | ~ || O || | | + | [_ | | | / \_ |___, || || | | + | || | | \ || || || | | + |_____||__| |____\____||____/ \___/ |__|__| diff --git a/theme/indymediaclassic/banner.txt b/theme/indymediaclassic/banner.txt new file mode 100644 index 000000000..8eb08d587 --- /dev/null +++ b/theme/indymediaclassic/banner.txt @@ -0,0 +1,8 @@ + / \ + | / ,--. \ | + \ \ `--' / / + ,------.,------. ,--. ,-----.,--. ,--.,-----. ,--. ,--. + | .---'| .--. '| |' .--./ \ `.' /' .-. '| ,'.| | + | `--, | '--' || || | '. / | | | || |' ' | + | `---.| | --' | |' '--'\ | | ' '-' '| | ` | + `------'`--' `--' `-----' `--' `-----' `--' `--' diff --git a/theme/indymediaclassic/logo.txt b/theme/indymediaclassic/logo.txt new file mode 100644 index 000000000..8eb08d587 --- /dev/null +++ b/theme/indymediaclassic/logo.txt @@ -0,0 +1,8 @@ + / \ + | / ,--. \ | + \ \ `--' / / + ,------.,------. ,--. ,-----.,--. ,--.,-----. ,--. ,--. + | .---'| .--. '| |' .--./ \ `.' /' .-. '| ,'.| | + | `--, | '--' || || | '. / | | | || |' ' | + | `---.| | --' | |' '--'\ | | ' '-' '| | ` | + `------'`--' `--' `-----' `--' `-----' `--' `--' diff --git a/theme/indymediamodern/banner.txt b/theme/indymediamodern/banner.txt new file mode 100644 index 000000000..8eb08d587 --- /dev/null +++ b/theme/indymediamodern/banner.txt @@ -0,0 +1,8 @@ + / \ + | / ,--. \ | + \ \ `--' / / + ,------.,------. ,--. ,-----.,--. ,--.,-----. ,--. ,--. + | .---'| .--. '| |' .--./ \ `.' /' .-. '| ,'.| | + | `--, | '--' || || | '. / | | | || |' ' | + | `---.| | --' | |' '--'\ | | ' '-' '| | ` | + `------'`--' `--' `-----' `--' `-----' `--' `--' diff --git a/theme/indymediamodern/logo.txt b/theme/indymediamodern/logo.txt new file mode 100644 index 000000000..8eb08d587 --- /dev/null +++ b/theme/indymediamodern/logo.txt @@ -0,0 +1,8 @@ + / \ + | / ,--. \ | + \ \ `--' / / + ,------.,------. ,--. ,-----.,--. ,--.,-----. ,--. ,--. + | .---'| .--. '| |' .--./ \ `.' /' .-. '| ,'.| | + | `--, | '--' || || | '. / | | | || |' ' | + | `---.| | --' | |' '--'\ | | ' '-' '| | ` | + `------'`--' `--' `-----' `--' `-----' `--' `--' diff --git a/theme/lcd/banner.txt b/theme/lcd/banner.txt new file mode 100644 index 000000000..ab13c6635 --- /dev/null +++ b/theme/lcd/banner.txt @@ -0,0 +1,6 @@ + _______ ______ _____ ______ _ _ _____ ______ + (_______|_____ (_____) _____) | | |/ ___ \| ___ \ + _____ _____) ) _ | / | |___| | | | | | | | + | ___) | ____/ | || | \_____/| | | | | | | + | |_____| | _| || \_____ ___ | |___| | | | | + |_______)_| (_____)______) (___) \_____/|_| |_| diff --git a/theme/lcd/logo.txt b/theme/lcd/logo.txt new file mode 100644 index 000000000..ab13c6635 --- /dev/null +++ b/theme/lcd/logo.txt @@ -0,0 +1,6 @@ + _______ ______ _____ ______ _ _ _____ ______ + (_______|_____ (_____) _____) | | |/ ___ \| ___ \ + _____ _____) ) _ | / | |___| | | | | | | | + | ___) | ____/ | || | \_____/| | | | | | | + | |_____| | _| || \_____ ___ | |___| | | | | + |_______)_| (_____)______) (___) \_____/|_| |_| diff --git a/theme/light/banner.txt b/theme/light/banner.txt new file mode 100644 index 000000000..30208cbb8 --- /dev/null +++ b/theme/light/banner.txt @@ -0,0 +1,6 @@ + 88888888b 888888ba dP a88888b. dP dP .88888. 888888ba + 88 88 `8b 88 d8' `88 Y8. .8P d8' `8b 88 `8b + a88aaaa a88aaaa8P' 88 88 Y8aa8P 88 88 88 88 + 88 88 88 88 88 88 88 88 88 + 88 88 88 Y8. .88 88 Y8. .8P 88 88 + 88888888P dP dP Y88888P' dP `8888P' dP dP diff --git a/theme/light/logo.txt b/theme/light/logo.txt new file mode 100644 index 000000000..30208cbb8 --- /dev/null +++ b/theme/light/logo.txt @@ -0,0 +1,6 @@ + 88888888b 888888ba dP a88888b. dP dP .88888. 888888ba + 88 88 `8b 88 d8' `88 Y8. .8P d8' `8b 88 `8b + a88aaaa a88aaaa8P' 88 88 Y8aa8P 88 88 88 88 + 88 88 88 88 88 88 88 88 88 + 88 88 88 Y8. .88 88 Y8. .8P 88 88 + 88888888P dP dP Y88888P' dP `8888P' dP dP diff --git a/theme/night/banner.txt b/theme/night/banner.txt new file mode 100644 index 000000000..1f8a0d9cb --- /dev/null +++ b/theme/night/banner.txt @@ -0,0 +1,14 @@ + ( ( + ) ) + ___ ___ ___ _____ _____ _ _ ........ + | __| _ \_ _/ __\ \ / / _ \| \| | | |] + | _|| _/| | (__ \ V / (_) | .` | \ / + |___|_| |___\___| |_| \___/|_|\_| \____/ + + + + + + + + diff --git a/theme/night/logo.txt b/theme/night/logo.txt new file mode 100644 index 000000000..1f8a0d9cb --- /dev/null +++ b/theme/night/logo.txt @@ -0,0 +1,14 @@ + ( ( + ) ) + ___ ___ ___ _____ _____ _ _ ........ + | __| _ \_ _/ __\ \ / / _ \| \| | | |] + | _|| _/| | (__ \ V / (_) | .` | \ / + |___|_| |___\___| |_| \___/|_|\_| \____/ + + + + + + + + diff --git a/theme/purple/banner.txt b/theme/purple/banner.txt new file mode 100644 index 000000000..7d86e2745 --- /dev/null +++ b/theme/purple/banner.txt @@ -0,0 +1,8 @@ + 888888888b 888888ba dP a88888b. dP dP .88888. 888888ba + 88 88 `8b 88 d8' `88 Y8. .8P d8' `8b 88 `8b + a88aaaa a88aaaa8P' 88 88 Y8aa8P 88 88 88 88 + 88 88 88 88 88 88 88 88 88 + 88 88 88 Y8. .88 88 Y8. .8P 88 88 + 88888888P' dP dP Y88888P' 88 `8888P' dP dP + 88 + dP diff --git a/theme/purple/logo.txt b/theme/purple/logo.txt new file mode 100644 index 000000000..7d86e2745 --- /dev/null +++ b/theme/purple/logo.txt @@ -0,0 +1,8 @@ + 888888888b 888888ba dP a88888b. dP dP .88888. 888888ba + 88 88 `8b 88 d8' `88 Y8. .8P d8' `8b 88 `8b + a88aaaa a88aaaa8P' 88 88 Y8aa8P 88 88 88 88 + 88 88 88 88 88 88 88 88 88 + 88 88 88 Y8. .88 88 Y8. .8P 88 88 + 88888888P' dP dP Y88888P' 88 `8888P' dP dP + 88 + dP diff --git a/theme/rc3/banner.txt b/theme/rc3/banner.txt new file mode 100644 index 000000000..ffe9419c0 --- /dev/null +++ b/theme/rc3/banner.txt @@ -0,0 +1,8 @@ + __ + , ," e`--o + (( ( | __,' + \\~-------' \_;/ + ( / + /) .______. ) + (( ( (( ( + ``-' ``-' diff --git a/theme/rc3/logo.txt b/theme/rc3/logo.txt new file mode 100644 index 000000000..388fef656 --- /dev/null +++ b/theme/rc3/logo.txt @@ -0,0 +1,8 @@ + 8888888888 8888888b. 8888888 .d8888b. Y88b d88P .d88888b. 888b 888 + 888 888 Y88b 888 d88P Y88b Y88b d88P d88P" "Y88b 8888b 888 + 888 888 888 888 888 888 Y88o88P 888 888 88888b 888 + 8888888 888 d88P 888 888 Y888P 888 888 888Y88b 888 + 888 8888888P" 888 888 888 888 888 888 Y88b888 + 888 888 888 888 888 888 888 888 888 Y88888 + 888 888 888 Y88b d88P 888 Y88b. .d88P 888 Y8888 + 8888888888 888 8888888 "Y8888P" 888 "Y88888P" 888 Y888 diff --git a/theme/solidaric/banner.txt b/theme/solidaric/banner.txt new file mode 100644 index 000000000..3a8fd200d --- /dev/null +++ b/theme/solidaric/banner.txt @@ -0,0 +1,9 @@ + oooooooooooo o8o + `888' `8 `"' + 888 oo.ooooo. oooo .ooooo. oooo ooo .ooooo. ooo. .oo. + 888oooo8 888' `88b `888 d88' `"Y8 `88. .8' d88' `88b `888P"Y88b + 888 " 888 888 888 888 `88..8' 888 888 888 888 + 888 o 888 888 888 888 .o8 `888' 888 888 888 888 + o888ooooood8 888bod8P' o888o `Y8bod8P' .8' `Y8bod8P' o888o o888o + 888 .o..P' + o888o `Y8P' diff --git a/theme/solidaric/logo.txt b/theme/solidaric/logo.txt new file mode 100644 index 000000000..3a8fd200d --- /dev/null +++ b/theme/solidaric/logo.txt @@ -0,0 +1,9 @@ + oooooooooooo o8o + `888' `8 `"' + 888 oo.ooooo. oooo .ooooo. oooo ooo .ooooo. ooo. .oo. + 888oooo8 888' `88b `888 d88' `"Y8 `88. .8' d88' `88b `888P"Y88b + 888 " 888 888 888 888 `88..8' 888 888 888 888 + 888 o 888 888 888 888 .o8 `888' 888 888 888 888 + o888ooooood8 888bod8P' o888o `Y8bod8P' .8' `Y8bod8P' o888o o888o + 888 .o..P' + o888o `Y8P' diff --git a/theme/starlight/banner.txt b/theme/starlight/banner.txt new file mode 100644 index 000000000..ab13c6635 --- /dev/null +++ b/theme/starlight/banner.txt @@ -0,0 +1,6 @@ + _______ ______ _____ ______ _ _ _____ ______ + (_______|_____ (_____) _____) | | |/ ___ \| ___ \ + _____ _____) ) _ | / | |___| | | | | | | | + | ___) | ____/ | || | \_____/| | | | | | | + | |_____| | _| || \_____ ___ | |___| | | | | + |_______)_| (_____)______) (___) \_____/|_| |_| diff --git a/theme/starlight/logo.txt b/theme/starlight/logo.txt new file mode 100644 index 000000000..ab13c6635 --- /dev/null +++ b/theme/starlight/logo.txt @@ -0,0 +1,6 @@ + _______ ______ _____ ______ _ _ _____ ______ + (_______|_____ (_____) _____) | | |/ ___ \| ___ \ + _____ _____) ) _ | / | |___| | | | | | | | + | ___) | ____/ | || | \_____/| | | | | | | + | |_____| | _| || \_____ ___ | |___| | | | | + |_______)_| (_____)______) (___) \_____/|_| |_| diff --git a/theme/zen/banner.txt b/theme/zen/banner.txt new file mode 100644 index 000000000..79de0204a --- /dev/null +++ b/theme/zen/banner.txt @@ -0,0 +1,6 @@ + + _______ _____ _____ _______ __ __ _____ __ _ _=_ + | | | | | \ / | | |\ | q(-_-)p + |______ |_____| | | \_/ | | | \ | ,\___/\ + | | | | | | | | \ | ( _ _ ) + |______ | __|__ |_____ | |_____| | \| (_\_\_|_/_) diff --git a/theme/zen/logo.txt b/theme/zen/logo.txt new file mode 100644 index 000000000..79de0204a --- /dev/null +++ b/theme/zen/logo.txt @@ -0,0 +1,6 @@ + + _______ _____ _____ _______ __ __ _____ __ _ _=_ + | | | | | \ / | | |\ | q(-_-)p + |______ |_____| | | \_/ | | | \ | ,\___/\ + | | | | | | | | \ | ( _ _ ) + |______ | __|__ |_____ | |_____| | \| (_\_\_|_/_) diff --git a/translations/ar.json b/translations/ar.json index 087f1bc9d..b3a408074 100644 --- a/translations/ar.json +++ b/translations/ar.json @@ -366,5 +366,6 @@ "Version": "الإصدار", "Skip to timeline": "تخطي إلى الجدول الزمني", "Skip to Newswire": "انتقل إلى Newswire", - "Skip to Links": "تخطي إلى روابط الويب" + "Skip to Links": "تخطي إلى روابط الويب", + "Publish a blog article": "نشر مقال بلوق" } diff --git a/translations/ca.json b/translations/ca.json index 17b1414f4..232ee4300 100644 --- a/translations/ca.json +++ b/translations/ca.json @@ -366,5 +366,6 @@ "Version": "Versió", "Skip to timeline": "Ves a la cronologia", "Skip to Newswire": "Vés a Newswire", - "Skip to Links": "Vés als enllaços web" + "Skip to Links": "Vés als enllaços web", + "Publish a blog article": "Publicar un article del bloc" } diff --git a/translations/cy.json b/translations/cy.json index 26813ecc2..55b4b95e1 100644 --- a/translations/cy.json +++ b/translations/cy.json @@ -366,5 +366,6 @@ "Version": "Fersiwn", "Skip to timeline": "Neidio i'r llinell amser", "Skip to Newswire": "Neidio i Newswire", - "Skip to Links": "Neidio i Dolenni Gwe" + "Skip to Links": "Neidio i Dolenni Gwe", + "Publish a blog article": "Cyhoeddi erthygl blog" } diff --git a/translations/de.json b/translations/de.json index cb0fa5c24..140712ebd 100644 --- a/translations/de.json +++ b/translations/de.json @@ -366,5 +366,6 @@ "Version": "Ausführung", "Skip to timeline": "Zur Zeitleiste springen", "Skip to Newswire": "Springe zu Newswire", - "Skip to Links": "Springe zu Weblinks" + "Skip to Links": "Springe zu Weblinks", + "Publish a blog article": "Veröffentlichen Sie einen Blog-Artikel" } diff --git a/translations/en.json b/translations/en.json index bdf30b608..77da14052 100644 --- a/translations/en.json +++ b/translations/en.json @@ -366,5 +366,6 @@ "Version": "Version", "Skip to timeline": "Skip to timeline", "Skip to Newswire": "Skip to Newswire", - "Skip to Links": "Skip to Links" + "Skip to Links": "Skip to Links", + "Publish a blog article": "Publish a blog article" } diff --git a/translations/es.json b/translations/es.json index 602d20746..cf09d1446 100644 --- a/translations/es.json +++ b/translations/es.json @@ -366,5 +366,6 @@ "Version": "Versión", "Skip to timeline": "Saltar a la línea de tiempo", "Skip to Newswire": "Saltar a Newswire", - "Skip to Links": "Saltar a enlaces web" + "Skip to Links": "Saltar a enlaces web", + "Publish a blog article": "Publica un artículo de blog" } diff --git a/translations/fr.json b/translations/fr.json index 2506982e9..ac51b24fa 100644 --- a/translations/fr.json +++ b/translations/fr.json @@ -366,5 +366,6 @@ "Version": "Version", "Skip to timeline": "Passer à la chronologie", "Skip to Newswire": "Passer à Newswire", - "Skip to Links": "Passer aux liens Web" + "Skip to Links": "Passer aux liens Web", + "Publish a blog article": "Publier un article de blog" } diff --git a/translations/ga.json b/translations/ga.json index 169fd5e3e..5cff4c525 100644 --- a/translations/ga.json +++ b/translations/ga.json @@ -366,5 +366,6 @@ "Version": "Leagan", "Skip to timeline": "Scipeáil chuig an amlíne", "Skip to Newswire": "Scipeáil chuig Newswire", - "Skip to Links": "Scipeáil chuig Naisc Ghréasáin" + "Skip to Links": "Scipeáil chuig Naisc Ghréasáin", + "Publish a blog article": "Foilsigh alt blagála" } diff --git a/translations/hi.json b/translations/hi.json index def3d5d1f..a83d8d5a9 100644 --- a/translations/hi.json +++ b/translations/hi.json @@ -366,5 +366,6 @@ "Version": "संस्करण", "Skip to timeline": "टाइमलाइन पर जाएं", "Skip to Newswire": "Newswire पर जाएं", - "Skip to Links": "वेब लिंक पर जाएं" + "Skip to Links": "वेब लिंक पर जाएं", + "Publish a blog article": "एक ब्लॉग लेख प्रकाशित करें" } diff --git a/translations/it.json b/translations/it.json index fc13ee792..e7082ff98 100644 --- a/translations/it.json +++ b/translations/it.json @@ -366,5 +366,6 @@ "Version": "Versione", "Skip to timeline": "Passa alla sequenza temporale", "Skip to Newswire": "Passa a Newswire", - "Skip to Links": "Passa a collegamenti Web" + "Skip to Links": "Passa a collegamenti Web", + "Publish a blog article": "Pubblica un articolo sul blog" } diff --git a/translations/ja.json b/translations/ja.json index e5de8f525..38d6685a4 100644 --- a/translations/ja.json +++ b/translations/ja.json @@ -366,5 +366,6 @@ "Version": "バージョン", "Skip to timeline": "タイムラインにスキップ", "Skip to Newswire": "Newswireにスキップ", - "Skip to Links": "Webリンクにスキップ" + "Skip to Links": "Webリンクにスキップ", + "Publish a blog article": "ブログ記事を公開する" } diff --git a/translations/oc.json b/translations/oc.json index a6d62a6e0..7cd70a858 100644 --- a/translations/oc.json +++ b/translations/oc.json @@ -362,5 +362,6 @@ "Version": "Version", "Skip to timeline": "Skip to timeline", "Skip to Newswire": "Skip to Newswire", - "Skip to Links": "Skip to Links" + "Skip to Links": "Skip to Links", + "Publish a blog article": "Publish a blog article" } diff --git a/translations/pt.json b/translations/pt.json index d0f485ca5..2abe336bf 100644 --- a/translations/pt.json +++ b/translations/pt.json @@ -366,5 +366,6 @@ "Version": "Versão", "Skip to timeline": "Pular para a linha do tempo", "Skip to Newswire": "Pular para Newswire", - "Skip to Links": "Pular para links da web" + "Skip to Links": "Pular para links da web", + "Publish a blog article": "Publique um artigo de blog" } diff --git a/translations/ru.json b/translations/ru.json index 14eb8b5db..b75628208 100644 --- a/translations/ru.json +++ b/translations/ru.json @@ -366,5 +366,6 @@ "Version": "Версия", "Skip to timeline": "Перейти к временной шкале", "Skip to Newswire": "Перейти к ленте новостей", - "Skip to Links": "Перейти к веб-ссылкам" + "Skip to Links": "Перейти к веб-ссылкам", + "Publish a blog article": "Опубликовать статью в блоге" } diff --git a/translations/zh.json b/translations/zh.json index b75b33b3f..ea0dcce39 100644 --- a/translations/zh.json +++ b/translations/zh.json @@ -366,5 +366,6 @@ "Version": "版", "Skip to timeline": "跳到时间线", "Skip to Newswire": "跳到新闻专线", - "Skip to Links": "跳到网页链接" + "Skip to Links": "跳到网页链接", + "Publish a blog article": "发布博客文章" } diff --git a/utils.py b/utils.py index 3e7c8c4ec..f024a2b98 100644 --- a/utils.py +++ b/utils.py @@ -494,10 +494,20 @@ def evilIncarnate() -> []: def isEvil(domain: str) -> bool: + # https://www.youtube.com/watch?v=5qw1hcevmdU if not isinstance(domain, str): print('WARN: Malformed domain ' + str(domain)) return True - # https://www.youtube.com/watch?v=5qw1hcevmdU + # if a domain contains any of these strings then it is + # declaring itself to be hostile + evilEmporium = ( + 'nazi', 'extremis', 'extreemis', 'gendercritic', + 'kiwifarm', 'illegal', 'raplst', 'rapist', + 'antivax', 'plandemic' + ) + for hostileStr in evilEmporium: + if hostileStr in domain: + return True evilDomains = evilIncarnate() for concentratedEvil in evilDomains: if domain.endswith(concentratedEvil): diff --git a/webapp_column_right.py b/webapp_column_right.py index b245a5c6e..1b4276515 100644 --- a/webapp_column_right.py +++ b/webapp_column_right.py @@ -50,7 +50,8 @@ def getRightColumnContent(baseDir: str, nickname: str, domainFull: str, publishButtonAtTop: bool, authorized: bool, showHeaderImage: bool, - theme: str) -> str: + theme: str, + defaultTimeline: str) -> str: """Returns html content for the right column """ htmlStr = '' @@ -62,10 +63,13 @@ def getRightColumnContent(baseDir: str, nickname: str, domainFull: str, if authorized: # only show the publish button if logged in, otherwise replace it with # a login button + titleStr = translate['Publish a blog article'] + if defaultTimeline == 'tlfeatures': + titleStr = translate['Publish a news article'] publishButtonStr = \ ' ' + \ + '/users/' + nickname + '/newblog?nodropdown" ' + \ + 'title="' + titleStr + '">' + \ '\n' else: @@ -158,13 +162,16 @@ def getRightColumnContent(baseDir: str, nickname: str, domainFull: str, # show publish icon at top if showPublishButton: if showPublishAsIcon: + titleStr = translate['Publish a blog article'] + if defaultTimeline == 'tlfeatures': + titleStr = translate['Publish a news article'] htmlStr += \ ' ' + \ + '/users/' + nickname + '/newblog?nodropdown">' + \ '' + \
-                translate['Publish a news article'] + '\n' if editImageClass == 'rightColEdit': @@ -485,7 +492,8 @@ def htmlNewswireMobile(cssCache: {}, baseDir: str, nickname: str, newswire, positiveVoting, False, timelinePath, showPublishButton, showPublishAsIcon, rssIconAtTop, False, - authorized, False, theme) + authorized, False, theme, + defaultTimeline) else: if editor: htmlStr += '


\n' diff --git a/webapp_create_post.py b/webapp_create_post.py index 0c8ca1fd1..6387f9c5a 100644 --- a/webapp_create_post.py +++ b/webapp_create_post.py @@ -71,19 +71,25 @@ def _htmlNewPostDropDown(scopeIcon: str, scopeDescription: str, dropdownDMSuffix: str, dropdownReminderSuffix: str, dropdownEventSuffix: str, - dropdownReportSuffix: str) -> str: + dropdownReportSuffix: str, + noDropDown: bool) -> str: """Returns the html for a drop down list of new post types """ dropDownContent = '\n' + return dropDownContent + + dropDownContent += ' \n' + dropDownContent += '\n' return dropDownContent @@ -171,7 +177,7 @@ def htmlNewPost(cssCache: {}, mediaInstance: bool, translate: {}, nickname: str, domain: str, domainFull: str, defaultTimeline: str, newswire: {}, - theme: str) -> str: + theme: str, noDropDown: bool) -> str: """New post screen """ replyStr = '' @@ -641,7 +647,8 @@ def htmlNewPost(cssCache: {}, mediaInstance: bool, translate: {}, dropdownDMSuffix, dropdownReminderSuffix, dropdownEventSuffix, - dropdownReportSuffix) + dropdownReportSuffix, + noDropDown) else: if not shareDescription: # reporting a post to moderator diff --git a/webapp_frontscreen.py b/webapp_frontscreen.py index 97aadb938..4e5ad14fc 100644 --- a/webapp_frontscreen.py +++ b/webapp_frontscreen.py @@ -169,7 +169,8 @@ def htmlFrontScreen(rssIconAtTop: bool, httpPrefix, translate, False, False, newswire, False, False, None, False, False, - False, True, authorized, True, theme) + False, True, authorized, True, theme, + defaultTimeline) profileFooterStr += ' \n' profileFooterStr += ' \n' profileFooterStr += ' \n' diff --git a/webapp_headerbuttons.py b/webapp_headerbuttons.py index 29052c322..bf922d588 100644 --- a/webapp_headerbuttons.py +++ b/webapp_headerbuttons.py @@ -53,25 +53,25 @@ def headerButtonsTimeline(defaultTimeline: str, if defaultTimeline == 'tlmedia': tlStr += \ '' elif defaultTimeline == 'tlblogs': tlStr += \ '' elif defaultTimeline == 'tlfeatures': tlStr += \ '' else: tlStr += \ '' @@ -83,7 +83,7 @@ def headerButtonsTimeline(defaultTimeline: str, if not featuresHeader: tlStr += \ '' @@ -92,8 +92,8 @@ def headerButtonsTimeline(defaultTimeline: str, nickname + '@' + domain + '/tlreplies.index' if os.path.isfile(repliesIndexFilename): tlStr += \ - '' @@ -102,14 +102,14 @@ def headerButtonsTimeline(defaultTimeline: str, if not minimal and not featuresHeader: tlStr += \ '' else: if not minimal: tlStr += \ '' @@ -123,14 +123,14 @@ def headerButtonsTimeline(defaultTimeline: str, titleStr = translate['Article'] tlStr += \ '' else: if not minimal: tlStr += \ '' @@ -140,7 +140,7 @@ def headerButtonsTimeline(defaultTimeline: str, if not featuresHeader: tlStr += \ '' @@ -155,14 +155,14 @@ def headerButtonsTimeline(defaultTimeline: str, happeningStr += \ '' + \ + '?day=' + str(now.day) + '" tabindex="-1">' + \ '' else: happeningStr += \ '' + \ + '?day=' + str(now.day) + '" tabindex="-1">' + \ '' @@ -171,12 +171,14 @@ def headerButtonsTimeline(defaultTimeline: str, if not iconsAsButtons: happeningStr += \ '' else: happeningStr += \ '' else: # happening this week button @@ -184,12 +186,14 @@ def headerButtonsTimeline(defaultTimeline: str, if not iconsAsButtons: happeningStr += \ '' else: happeningStr += \ '' if not featuresHeader: @@ -197,7 +201,8 @@ def headerButtonsTimeline(defaultTimeline: str, tlStr += \ '' # add other buttons @@ -219,7 +224,7 @@ def headerButtonsTimeline(defaultTimeline: str, # the search button tlStr += \ '' @@ -245,7 +250,7 @@ def headerButtonsTimeline(defaultTimeline: str, else: tlStr += \ '' @@ -262,13 +267,13 @@ def headerButtonsTimeline(defaultTimeline: str, else: tlStr += \ '' if featuresHeader: tlStr += \ - '' + \ + '' + \ '' @@ -286,7 +291,7 @@ def headerButtonsTimeline(defaultTimeline: str, tlStr += \ '' @@ -304,13 +309,13 @@ def headerButtonsTimeline(defaultTimeline: str, tlStr += \ '' if featuresHeader: tlStr += \ - '' + \ + '' + \ '' diff --git a/webapp_login.py b/webapp_login.py index 5e4188be8..b0e893d08 100644 --- a/webapp_login.py +++ b/webapp_login.py @@ -13,6 +13,8 @@ from utils import getConfigParam from utils import noOfAccounts from webapp_utils import htmlHeaderWithExternalStyle from webapp_utils import htmlFooter +from webapp_utils import htmlKeyboardNavigation +from theme import getTextModeLogo def htmlGetLoginCredentials(loginParams: str, @@ -75,6 +77,9 @@ def htmlLogin(cssCache: {}, translate: {}, loginImageFilename = baseDir + '/accounts/' + loginImage copyfile(baseDir + '/img/login.png', loginImageFilename) + textModeLogo = getTextModeLogo(baseDir) + textModeLogoHtml = htmlKeyboardNavigation(textModeLogo, {}) + if os.path.isfile(baseDir + '/accounts/login-background-custom.jpg'): if not os.path.isfile(baseDir + '/accounts/login-background.jpg'): copyfile(baseDir + '/accounts/login-background-custom.jpg', @@ -139,8 +144,7 @@ def htmlLogin(cssCache: {}, translate: {}, loginForm += '
\n' loginForm += '
\n' instanceTitle = getConfigParam(baseDir, 'instanceTitle') - if not instanceTitle: - instanceTitle = "Epicyon" + loginForm += textModeLogoHtml + '\n' loginForm += \ ' ' + instanceTitle + '\n' diff --git a/webapp_moderation.py b/webapp_moderation.py index 27140ec23..87d11da47 100644 --- a/webapp_moderation.py +++ b/webapp_moderation.py @@ -43,7 +43,8 @@ def htmlModeration(cssCache: {}, defaultTimeline: str, publishButtonAtTop: bool, authorized: bool, moderationActionStr: str, theme: str, peertubeInstances: [], - allowLocalNetworkAccess: bool) -> str: + allowLocalNetworkAccess: bool, + textModeBanner: str) -> str: """Show the moderation feed as html This is what you see when selecting the "mod" timeline """ @@ -58,7 +59,8 @@ def htmlModeration(cssCache: {}, defaultTimeline: str, showPublishAsIcon, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, authorized, moderationActionStr, theme, - peertubeInstances, allowLocalNetworkAccess) + peertubeInstances, allowLocalNetworkAccess, + textModeBanner) def htmlAccountInfo(cssCache: {}, translate: {}, diff --git a/webapp_post.py b/webapp_post.py index c9ec866e0..dd4c9a24b 100644 --- a/webapp_post.py +++ b/webapp_post.py @@ -244,15 +244,19 @@ def _getAvatarImageHtml(showAvatarOptions: bool, ';' + str(pageNumber) + ';' + avatarUrl + messageIdStr + '">\n' avatarLink += \ ' \n' else: # don't link to the person options for the news account avatarLink += \ ' \n' return avatarLink.strip() @@ -388,12 +392,14 @@ def _getAnnounceIconHtml(nickname: str, domainFull: str, # don't allow announce/repeat of your own posts announceIcon = 'repeat_inactive.png' announceLink = 'repeat' + announceEmoji = '' if not isPublicRepeat: announceLink = 'repeatprivate' announceTitle = translate['Repeat this post'] if announcedByPerson(postJsonObject, nickname, domainFull): announceIcon = 'repeat.png' + announceEmoji = '🔁 ' if not isPublicRepeat: announceLink = 'unrepeatprivate' announceTitle = translate['Undo the repeat'] @@ -409,7 +415,7 @@ def _getAnnounceIconHtml(nickname: str, domainFull: str, announceStr += \ ' ' + \ '' + translate['Repeat this post'] + \
+            '\n' return announceStr @@ -430,6 +436,7 @@ def _getLikeIconHtml(nickname: str, domainFull: str, likeIcon = 'like_inactive.png' likeLink = 'like' likeTitle = translate['Like this post'] + likeEmoji = '' likeCount = noOfLikes(postJsonObject) _logPostTiming(enableTimingLog, postStartTime, '12.1') @@ -447,6 +454,7 @@ def _getLikeIconHtml(nickname: str, domainFull: str, likeIcon = 'like.png' likeLink = 'unlike' likeTitle = translate['Undo the like'] + likeEmoji = '👍 ' _logPostTiming(enableTimingLog, postStartTime, '12.2') @@ -467,7 +475,7 @@ def _getLikeIconHtml(nickname: str, domainFull: str, likeStr += \ ' ' + \ '' + likeTitle + \
+            '\n' return likeStr @@ -489,10 +497,12 @@ def _getBookmarkIconHtml(nickname: str, domainFull: str, bookmarkIcon = 'bookmark_inactive.png' bookmarkLink = 'bookmark' + bookmarkEmoji = '' bookmarkTitle = translate['Bookmark this post'] if bookmarkedByPerson(postJsonObject, nickname, domainFull): bookmarkIcon = 'bookmark.png' bookmarkLink = 'unbookmark' + bookmarkEmoji = '🔖 ' bookmarkTitle = translate['Undo the bookmark'] _logPostTiming(enableTimingLog, postStartTime, '12.6') bookmarkStr = \ @@ -505,7 +515,7 @@ def _getBookmarkIconHtml(nickname: str, domainFull: str, bookmarkStr += \ ' ' + \ '' + \
-        bookmarkTitle + ' |\n' return bookmarkStr @@ -548,7 +558,7 @@ def _getMuteIconHtml(isMuted: bool, translate['Undo mute'] + '">\n' muteStr += \ ' ' + \ - '' + translate['Undo mute'] + \
+            '<img loading=\n' return muteStr diff --git a/webapp_profile.py b/webapp_profile.py index 92d4dff48..b4859a6d9 100644 --- a/webapp_profile.py +++ b/webapp_profile.py @@ -40,6 +40,8 @@ from jami import getJamiAddress from filters import isFiltered from follow import isFollowerOfPerson from webapp_frontscreen import htmlFrontScreen +from webapp_utils import htmlKeyboardNavigation +from webapp_utils import htmlHideFromScreenReader from webapp_utils import scheduledPostsExist from webapp_utils import getPersonAvatarUrl from webapp_utils import htmlHeaderWithExternalStyle @@ -472,6 +474,7 @@ def htmlProfile(rssIconAtTop: bool, newswire: {}, theme: str, dormantMonths: int, peertubeInstances: [], allowLocalNetworkAccess: bool, + textModeBanner: str, extraJson=None, pageNumber=None, maxItemsPerPage=None) -> str: """Show the profile page as html @@ -707,16 +710,37 @@ def htmlProfile(rssIconAtTop: bool, movedTo, alsoKnownAs, pinnedContent) - # Links for keyboard navigation - profileStr = \ - '\n' + # keyboard navigation + userPathStr = '/users/' + nickname + deft = defaultTimeline + menuTimeline = \ + htmlHideFromScreenReader('🏠') + ' ' + \ + translate['Switch to timeline view'] + menuEdit = \ + htmlHideFromScreenReader('✍') + ' ' + translate['Edit'] + menuFollowing = \ + htmlHideFromScreenReader('👥') + ' ' + translate['Following'] + menuFollowers = \ + htmlHideFromScreenReader('👪') + ' ' + translate['Followers'] + menuRoles = \ + htmlHideFromScreenReader('🤚') + ' ' + translate['Roles'] + menuSkills = \ + htmlHideFromScreenReader('🛠') + ' ' + translate['Skills'] + menuShares = \ + htmlHideFromScreenReader('🤝') + ' ' + translate['Shares'] + menuLogout = \ + htmlHideFromScreenReader('❎') + ' ' + translate['Logout'] + navLinks = { + menuTimeline: userPathStr + '/' + deft, + menuEdit: userPathStr + '/editprofile', + menuFollowing: userPathStr + '/following#timeline', + menuFollowers: userPathStr + '/followers#timeline', + menuRoles: userPathStr + '/roles#timeline', + menuSkills: userPathStr + '/skills#timeline', + menuShares: userPathStr + '/shares#timeline', + menuLogout: '/logout' + } + profileStr = htmlKeyboardNavigation(textModeBanner, navLinks) profileStr += profileHeaderStr + donateSection profileStr += '
\n' @@ -750,6 +774,9 @@ def htmlProfile(rssIconAtTop: bool, profileStr += ' ' profileStr += '
' + # start of #timeline + profileStr += '
\n' + profileStr += followApprovalsSection cssFilename = baseDir + '/epicyon-profile.css' @@ -804,6 +831,8 @@ def htmlProfile(rssIconAtTop: bool, _htmlProfileShares(actor, translate, nickname, domainFull, extraJson) + licenseStr + # end of #timeline + profileStr += '
' instanceTitle = \ getConfigParam(baseDir, 'instanceTitle') @@ -985,7 +1014,8 @@ def _htmlProfileShares(actor: str, translate: {}, def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str, domain: str, port: int, httpPrefix: str, defaultTimeline: str, theme: str, - peertubeInstances: []) -> str: + peertubeInstances: [], + textModeBanner: str) -> str: """Shows the edit profile screen """ imageFormats = getImageFormats() @@ -1332,13 +1362,26 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str, getConfigParam(baseDir, 'instanceTitle') editProfileForm = htmlHeaderWithExternalStyle(cssFilename, instanceTitle) + # keyboard navigation + userPathStr = '/users/' + nickname + userTimalineStr = '/users/' + nickname + '/' + defaultTimeline + menuTimeline = \ + htmlHideFromScreenReader('🏠') + ' ' + \ + translate['Switch to timeline view'] + menuProfile = \ + htmlHideFromScreenReader('👤') + ' ' + \ + translate['Switch to profile view'] + navLinks = { + menuProfile: userPathStr, + menuTimeline: userTimalineStr + } + editProfileForm += htmlKeyboardNavigation(textModeBanner, navLinks) + # top banner editProfileForm += \ - '\n' + '' editProfileForm += '\n' + '/users/' + nickname + '/' + bannerFile + '" alt="" />\n' editProfileForm += \ ' str: + defaultTimeline: str, theme: str, + textModeBanner: str) -> str: """Search called from the timeline icon """ actor = path.replace('/search', '') @@ -340,10 +342,14 @@ def htmlSearch(cssCache: {}, translate: {}, searchBannerFile, searchBannerFilename = \ getSearchBannerFile(baseDir, searchNickname, domain, theme) + textModeBannerStr = htmlKeyboardNavigation(textModeBanner, {}) + if textModeBannerStr is None: + textModeBannerStr = '' + if os.path.isfile(searchBannerFilename): usersPath = '/users/' + searchNickname followStr += \ - '
\n' + \ + '
\n' + textModeBannerStr + \ '\n' diff --git a/webapp_timeline.py b/webapp_timeline.py index 66bbf7837..07c1843fa 100644 --- a/webapp_timeline.py +++ b/webapp_timeline.py @@ -14,6 +14,8 @@ from utils import isEditor from utils import removeIdEnding from follow import followerApprovalActive from person import isPersonSnoozed +from webapp_utils import htmlKeyboardNavigation +from webapp_utils import htmlHideFromScreenReader from webapp_utils import htmlPostSeparator from webapp_utils import getBannerFile from webapp_utils import htmlHeaderWithExternalStyle @@ -64,7 +66,8 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, moderationActionStr: str, theme: str, peertubeInstances: [], - allowLocalNetworkAccess: bool) -> str: + allowLocalNetworkAccess: bool, + textModeBanner: str) -> str: """Show the timeline as html """ enableTimingLog = False @@ -279,14 +282,14 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, if not iconsAsButtons: newPostButtonStr += \ '| ' + translate['Create a new DM'] + \
                 '\n' else: newPostButtonStr += \ - '' + \ + '' + \ '' elif (boxName == 'tlblogs' or @@ -309,28 +312,28 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, if not iconsAsButtons: newPostButtonStr += \ '| ' + \
                 translate['Create a new event'] + \
                 '\n' else: newPostButtonStr += \ - '' + \ + '' + \ '' elif boxName == 'tlshares': if not iconsAsButtons: newPostButtonStr += \ '| ' + \
                 translate['Create a new shared item'] + \
                 '\n' else: newPostButtonStr += \ - '' + \ + '' + \ '' else: @@ -363,25 +366,74 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, '' - # This creates a link to skip to the timeline and change to - # profile view when accessed within lynx, but should be - # invisible in a graphical web browser - tlStr += \ - '\n' + # keyboard navigation + calendarStr = translate['Calendar'] + if newCalendarEvent: + calendarStr = '' + calendarStr + '' + dmStr = translate['DM'] + if newDM: + dmStr = '' + dmStr + '' + repliesStr = translate['Replies'] + if newReply: + repliesStr = '' + repliesStr + '' + sharesStr = translate['Shares'] + if newShare: + sharesStr = '' + sharesStr + '' + menuProfile = \ + htmlHideFromScreenReader('👤') + ' ' + \ + translate['Switch to profile view'] + menuInbox = \ + htmlHideFromScreenReader('📥') + ' ' + translate['Inbox'] + menuOutbox = \ + htmlHideFromScreenReader('📤') + ' ' + translate['Outbox'] + menuSearch = \ + htmlHideFromScreenReader('🔍') + ' ' + \ + translate['Search and follow'] + menuCalendar = \ + htmlHideFromScreenReader('📅') + ' ' + calendarStr + menuDM = \ + htmlHideFromScreenReader('📩') + ' ' + dmStr + menuReplies = \ + htmlHideFromScreenReader('📨') + ' ' + repliesStr + menuBookmarks = \ + htmlHideFromScreenReader('🔖') + ' ' + \ + translate['Bookmarks'] + menuShares = \ + htmlHideFromScreenReader('🤝') + ' ' + sharesStr + menuEvents = \ + htmlHideFromScreenReader('🎫') + ' ' + translate['Events'] + menuBlogs = \ + htmlHideFromScreenReader('📝') + ' ' + translate['Blogs'] + menuNewswire = \ + htmlHideFromScreenReader('📰') + ' ' + translate['Newswire'] + menuLinks = \ + htmlHideFromScreenReader('🔗') + ' ' + translate['Links'] + menuNewPost = \ + htmlHideFromScreenReader('➕') + ' ' + \ + translate['Create a new post'] + menuModeration = \ + htmlHideFromScreenReader('⚡️') + ' ' + \ + translate['Mod'] + navLinks = { + menuProfile: '/users/' + nickname, + menuInbox: usersPath + '/inbox#timeline', + menuSearch: usersPath + '/search', + menuNewPost: usersPath + '/newpost', + menuCalendar: usersPath + '/calendar', + menuDM: usersPath + '/dm#timeline', + menuReplies: usersPath + '/tlreplies#timeline', + menuOutbox: usersPath + '/inbox#timeline', + menuBookmarks: usersPath + '/tlbookmarks#timeline', + menuShares: usersPath + '/tlshares#timeline', + menuBlogs: usersPath + '/tlblogs#timeline', + menuEvents: usersPath + '/tlevents#timeline', + menuNewswire: '#newswire', + menuLinks: '#links' + } + if moderator: + navLinks[menuModeration] = usersPath + '/moderation#modtimeline' + tlStr += htmlKeyboardNavigation(textModeBanner, navLinks, + usersPath, translate, followApprovals) # banner and row of buttons tlStr += \ @@ -433,7 +485,6 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, leftColumnStr + ' \n' # center column containing posts tlStr += ' \n' - tlStr += '
\n' if not fullWidthTimelineButtonHeader: tlStr += \ @@ -451,12 +502,12 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, calendarImage, followApprovals, iconsAsButtons) - tlStr += '
\n' + tlStr += '
\n' # second row of buttons for moderator actions if moderator and boxName == 'moderation': tlStr += \ - '' tlStr += '
\n' idx = 'Nickname or URL. Block using *@domain or nickname@domain' @@ -473,40 +524,57 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, tlStr += \ ' \n' + '" alt="' + \ + translate['Information about current blocks/suspensions'] + \ + ' | " ' + \ + 'name="submitInfo" value="' + translate['Info'] + '">\n' tlStr += \ ' \n' tlStr += \ ' \n' + translate['Suspend the above account nickname'] + '" ' + \ + 'alt="' + \ + translate['Suspend the above account nickname'] + ' | " ' + \ + 'name="submitSuspend" value="' + translate['Suspend'] + '">\n' tlStr += \ ' \n' tlStr += \ ' \n' + translate['Block an account on another instance'] + '" ' + \ + 'alt="' + \ + translate['Block an account on another instance'] + ' | " ' + \ + 'name="submitBlock" value="' + translate['Block'] + '">\n' tlStr += \ ' \n' + translate['Unblock an account on another instance'] + '" ' + \ + 'alt="' + \ + translate['Unblock an account on another instance'] + ' | " ' + \ + 'name="submitUnblock" value="' + translate['Unblock'] + '">\n' tlStr += \ ' \n' + translate['Filter out words'] + '" ' + \ + 'alt="' + \ + translate['Filter out words'] + ' | " ' + \ + 'name="submitFilter" value="' + translate['Filter'] + '">\n' tlStr += \ ' \n' + translate['Unfilter words'] + '" ' + \ + 'alt="' + \ + translate['Unfilter words'] + ' | " ' + \ + 'name="submitUnfilter" value="' + translate['Unfilter'] + '">\n' tlStr += '
\n\n' @@ -522,8 +590,14 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, _logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '7') + # separator between posts which only appears in shell browsers + # such as Lynx and is not read by screen readers + textModeSeparator = \ + '

' + # page up arrow if pageNumber > 1: + tlStr += textModeSeparator tlStr += \ '
\n' + \ ' \n' + \ '
\n' + tlStr += textModeSeparator # end of timeline-posts tlStr += '
\n' @@ -634,8 +710,8 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, False, None, True, showPublishAsIcon, rssIconAtTop, publishButtonAtTop, - authorized, True, theme) - tlStr += '
\n' + authorized, True, theme, + defaultTimeline) tlStr += ' ' + \ rightColumnStr + ' \n' @@ -752,7 +828,8 @@ def htmlShares(cssCache: {}, defaultTimeline: str, publishButtonAtTop: bool, authorized: bool, theme: str, peertubeInstances: [], - allowLocalNetworkAccess: bool) -> str: + allowLocalNetworkAccess: bool, + textModeBanner: str) -> str: """Show the shares timeline as html """ manuallyApproveFollowers = \ @@ -773,7 +850,7 @@ def htmlShares(cssCache: {}, defaultTimeline: str, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, authorized, None, theme, peertubeInstances, - allowLocalNetworkAccess) + allowLocalNetworkAccess, textModeBanner) def htmlInbox(cssCache: {}, defaultTimeline: str, @@ -794,7 +871,8 @@ def htmlInbox(cssCache: {}, defaultTimeline: str, publishButtonAtTop: bool, authorized: bool, theme: str, peertubeInstances: [], - allowLocalNetworkAccess: bool) -> str: + allowLocalNetworkAccess: bool, + textModeBanner: str) -> str: """Show the inbox as html """ manuallyApproveFollowers = \ @@ -815,7 +893,7 @@ def htmlInbox(cssCache: {}, defaultTimeline: str, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, authorized, None, theme, peertubeInstances, - allowLocalNetworkAccess) + allowLocalNetworkAccess, textModeBanner) def htmlBookmarks(cssCache: {}, defaultTimeline: str, @@ -836,7 +914,8 @@ def htmlBookmarks(cssCache: {}, defaultTimeline: str, publishButtonAtTop: bool, authorized: bool, theme: str, peertubeInstances: [], - allowLocalNetworkAccess: bool) -> str: + allowLocalNetworkAccess: bool, + textModeBanner: str) -> str: """Show the bookmarks as html """ manuallyApproveFollowers = \ @@ -857,7 +936,7 @@ def htmlBookmarks(cssCache: {}, defaultTimeline: str, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, authorized, None, theme, peertubeInstances, - allowLocalNetworkAccess) + allowLocalNetworkAccess, textModeBanner) def htmlEvents(cssCache: {}, defaultTimeline: str, @@ -878,7 +957,8 @@ def htmlEvents(cssCache: {}, defaultTimeline: str, publishButtonAtTop: bool, authorized: bool, theme: str, peertubeInstances: [], - allowLocalNetworkAccess: bool) -> str: + allowLocalNetworkAccess: bool, + textModeBanner: str) -> str: """Show the events as html """ manuallyApproveFollowers = \ @@ -899,7 +979,7 @@ def htmlEvents(cssCache: {}, defaultTimeline: str, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, authorized, None, theme, peertubeInstances, - allowLocalNetworkAccess) + allowLocalNetworkAccess, textModeBanner) def htmlInboxDMs(cssCache: {}, defaultTimeline: str, @@ -920,7 +1000,8 @@ def htmlInboxDMs(cssCache: {}, defaultTimeline: str, publishButtonAtTop: bool, authorized: bool, theme: str, peertubeInstances: [], - allowLocalNetworkAccess: bool) -> str: + allowLocalNetworkAccess: bool, + textModeBanner: str) -> str: """Show the DM timeline as html """ return htmlTimeline(cssCache, defaultTimeline, @@ -936,7 +1017,7 @@ def htmlInboxDMs(cssCache: {}, defaultTimeline: str, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, authorized, None, theme, peertubeInstances, - allowLocalNetworkAccess) + allowLocalNetworkAccess, textModeBanner) def htmlInboxReplies(cssCache: {}, defaultTimeline: str, @@ -957,7 +1038,8 @@ def htmlInboxReplies(cssCache: {}, defaultTimeline: str, publishButtonAtTop: bool, authorized: bool, theme: str, peertubeInstances: [], - allowLocalNetworkAccess: bool) -> str: + allowLocalNetworkAccess: bool, + textModeBanner: str) -> str: """Show the replies timeline as html """ return htmlTimeline(cssCache, defaultTimeline, @@ -974,7 +1056,7 @@ def htmlInboxReplies(cssCache: {}, defaultTimeline: str, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, authorized, None, theme, peertubeInstances, - allowLocalNetworkAccess) + allowLocalNetworkAccess, textModeBanner) def htmlInboxMedia(cssCache: {}, defaultTimeline: str, @@ -995,7 +1077,8 @@ def htmlInboxMedia(cssCache: {}, defaultTimeline: str, publishButtonAtTop: bool, authorized: bool, theme: str, peertubeInstances: [], - allowLocalNetworkAccess: bool) -> str: + allowLocalNetworkAccess: bool, + textModeBanner: str) -> str: """Show the media timeline as html """ return htmlTimeline(cssCache, defaultTimeline, @@ -1012,7 +1095,7 @@ def htmlInboxMedia(cssCache: {}, defaultTimeline: str, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, authorized, None, theme, peertubeInstances, - allowLocalNetworkAccess) + allowLocalNetworkAccess, textModeBanner) def htmlInboxBlogs(cssCache: {}, defaultTimeline: str, @@ -1033,7 +1116,8 @@ def htmlInboxBlogs(cssCache: {}, defaultTimeline: str, publishButtonAtTop: bool, authorized: bool, theme: str, peertubeInstances: [], - allowLocalNetworkAccess: bool) -> str: + allowLocalNetworkAccess: bool, + textModeBanner: str) -> str: """Show the blogs timeline as html """ return htmlTimeline(cssCache, defaultTimeline, @@ -1050,7 +1134,7 @@ def htmlInboxBlogs(cssCache: {}, defaultTimeline: str, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, authorized, None, theme, peertubeInstances, - allowLocalNetworkAccess) + allowLocalNetworkAccess, textModeBanner) def htmlInboxFeatures(cssCache: {}, defaultTimeline: str, @@ -1072,7 +1156,8 @@ def htmlInboxFeatures(cssCache: {}, defaultTimeline: str, authorized: bool, theme: str, peertubeInstances: [], - allowLocalNetworkAccess: bool) -> str: + allowLocalNetworkAccess: bool, + textModeBanner: str) -> str: """Show the features timeline as html """ return htmlTimeline(cssCache, defaultTimeline, @@ -1089,7 +1174,7 @@ def htmlInboxFeatures(cssCache: {}, defaultTimeline: str, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, authorized, None, theme, peertubeInstances, - allowLocalNetworkAccess) + allowLocalNetworkAccess, textModeBanner) def htmlInboxNews(cssCache: {}, defaultTimeline: str, @@ -1110,7 +1195,8 @@ def htmlInboxNews(cssCache: {}, defaultTimeline: str, publishButtonAtTop: bool, authorized: bool, theme: str, peertubeInstances: [], - allowLocalNetworkAccess: bool) -> str: + allowLocalNetworkAccess: bool, + textModeBanner: str) -> str: """Show the news timeline as html """ return htmlTimeline(cssCache, defaultTimeline, @@ -1127,7 +1213,7 @@ def htmlInboxNews(cssCache: {}, defaultTimeline: str, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, authorized, None, theme, peertubeInstances, - allowLocalNetworkAccess) + allowLocalNetworkAccess, textModeBanner) def htmlOutbox(cssCache: {}, defaultTimeline: str, @@ -1148,7 +1234,8 @@ def htmlOutbox(cssCache: {}, defaultTimeline: str, publishButtonAtTop: bool, authorized: bool, theme: str, peertubeInstances: [], - allowLocalNetworkAccess: bool) -> str: + allowLocalNetworkAccess: bool, + textModeBanner: str) -> str: """Show the Outbox as html """ manuallyApproveFollowers = \ @@ -1166,4 +1253,4 @@ def htmlOutbox(cssCache: {}, defaultTimeline: str, showPublishAsIcon, fullWidthTimelineButtonHeader, iconsAsButtons, rssIconAtTop, publishButtonAtTop, authorized, None, theme, peertubeInstances, - allowLocalNetworkAccess) + allowLocalNetworkAccess, textModeBanner) diff --git a/webapp_utils.py b/webapp_utils.py index 1531c912f..1511b1408 100644 --- a/webapp_utils.py +++ b/webapp_utils.py @@ -878,3 +878,35 @@ def getAvatarImageUrl(session, avatarUrl = postActor + '/avatar.png' return avatarUrl + + +def htmlHideFromScreenReader(htmlStr: str) -> str: + """Returns html which is hidden from screen readers + """ + return '' + + +def htmlKeyboardNavigation(banner: str, links: {}, + usersPath=None, translate=None, + followApprovals=False) -> str: + """Given a set of links return the html for keyboard navigation + """ + htmlStr = '
' + return htmlStr