epicyon/webapp_timeline.py

1348 lines
55 KiB
Python
Raw Normal View History

2020-11-09 22:44:03 +00:00
__filename__ = "webapp_timeline.py"
__author__ = "Bob Mottram"
__license__ = "AGPL3+"
__version__ = "1.1.0"
__maintainer__ = "Bob Mottram"
__email__ = "bob@freedombone.net"
__status__ = "Production"
import os
import time
2020-12-16 11:19:16 +00:00
from utils import getFullDomain
2020-12-01 21:44:27 +00:00
from utils import isEditor
2020-11-09 22:44:03 +00:00
from utils import removeIdEnding
2020-11-24 14:07:38 +00:00
from utils import getConfigParam
2020-11-09 22:44:03 +00:00
from follow import followerApprovalActive
from person import isPersonSnoozed
from webapp_utils import htmlPostSeparator
from webapp_utils import getBannerFile
2020-11-24 14:07:38 +00:00
from webapp_utils import htmlHeaderWithExternalStyle, htmlHeaderWithExternalStyles
2020-11-09 22:44:03 +00:00
from webapp_utils import htmlFooter
from webapp_utils import sharesTimelineJson
2020-11-17 20:40:36 +00:00
from webapp_utils import htmlHighlightLabel
2020-11-09 22:44:03 +00:00
from webapp_post import preparePostFromHtmlCache
from webapp_post import individualPostAsHtml
from webapp_column_left import getLeftColumnContent
from webapp_column_right import getRightColumnContent
2020-11-19 11:39:14 +00:00
from webapp_headerbuttons import headerButtonsTimeline, headerNewsTabs
2020-11-09 22:44:03 +00:00
from posts import isModerator
def _logTimelineTiming(enableTimingLog: bool, timelineStartTime,
boxName: str, debugId: str) -> None:
2020-12-01 17:23:34 +00:00
"""Create a log of timings for performance tuning
"""
if not enableTimingLog:
return
timeDiff = int((time.time() - timelineStartTime) * 1000)
if timeDiff > 100:
print('TIMELINE TIMING ' +
boxName + ' ' + debugId + ' = ' + str(timeDiff))
2020-11-10 15:12:07 +00:00
def htmlTimeline(cssCache: {}, defaultTimeline: str,
recentPostsCache: {}, maxRecentPosts: int,
translate: {}, pageNumber: int,
itemsPerPage: int, session, baseDir: str,
cachedWebfingers: {}, personCache: {},
2020-11-10 15:12:07 +00:00
nickname: str, domain: str, port: int, timelineJson: {},
boxName: str, allowDeletion: bool,
httpPrefix: str, projectVersion: str,
manuallyApproveFollowers: bool,
minimal: bool,
YTReplacementDomain: str,
showPublishedDateOnly: bool,
newswire: {}, moderator: bool,
editor: bool,
positiveVoting: bool,
showPublishAsIcon: bool,
fullWidthTimelineButtonHeader: bool,
iconsAsButtons: bool,
rssIconAtTop: bool,
publishButtonAtTop: bool,
2020-12-09 23:30:15 +00:00
authorized: bool,
2020-12-20 17:26:38 +00:00
moderationActionStr: str,
2020-12-23 23:59:49 +00:00
theme: str,
peertubeInstances: []) -> str:
2020-11-10 15:12:07 +00:00
"""Show the timeline as html
2020-11-09 22:44:03 +00:00
"""
2020-12-01 17:23:34 +00:00
enableTimingLog = False
2020-11-10 15:12:07 +00:00
timelineStartTime = time.time()
2020-11-09 22:44:03 +00:00
2020-11-13 21:26:45 +00:00
# directory where icons are found
# This changes depending upon theme
iconsDir = getIconsDir(baseDir)
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
separatorStr = ''
if boxName != 'tlmedia':
separatorStr = htmlPostSeparator(baseDir, None)
2020-11-09 22:44:03 +00:00
2020-11-24 14:07:38 +00:00
cssFiles = []
# TODO: Clean up - default load only one base css file
# default css
cssFiles.append(baseDir + '/epicyon-profile.css')
2020-11-10 15:12:07 +00:00
if os.path.isfile(baseDir + '/epicyon.css'):
2020-11-24 14:07:38 +00:00
cssFiles[0] = baseDir + '/epicyon.css'
# TODO: Clean up and remove this override
cssFiles[0] = 'base.css'
# Get theme-specific css if exists - must be named '<theme-name>.css'
themeName = getConfigParam(baseDir, 'theme')
themePath = f'{baseDir}/theme/{themeName}.css'
if os.path.isfile(themePath):
cssFiles.append('theme/' + themeName + '.css')
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
# filename of the banner shown at the top
2020-12-20 17:29:15 +00:00
bannerFile, bannerFilename = \
getBannerFile(baseDir, nickname, domain, theme)
2020-11-09 22:44:03 +00:00
_logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '1')
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
# is the user a moderator?
if not moderator:
moderator = isModerator(baseDir, nickname)
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
# is the user a site editor?
if not editor:
editor = isEditor(baseDir, nickname)
2020-11-09 22:44:03 +00:00
_logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '2')
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
# get the full domain, including any port number
2020-12-16 11:19:16 +00:00
fullDomain = getFullDomain(domain, port)
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
usersPath = '/users/' + nickname
actor = httpPrefix + '://' + fullDomain + usersPath
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
showIndividualPostIcons = True
2020-11-13 21:26:45 +00:00
# benchmark 3
timeDiff = int((time.time() - timelineStartTime) * 1000)
if timeDiff > 100:
print('TIMELINE TIMING ' + boxName + ' 3 = ' + str(timeDiff))
2020-11-09 22:44:03 +00:00
# NOTE: This uses a variant function for multiple CSS files
# TODO: Figure out a better approach
2020-11-24 14:07:38 +00:00
tlStr = htmlHeaderWithExternalStyles(cssFiles)
# benchmark 4
timeDiff = int((time.time() - timelineStartTime) * 1000)
if timeDiff > 100:
print('TIMELINE TIMING ' + boxName + ' 4 = ' + str(timeDiff))
2020-11-10 15:12:07 +00:00
_logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '4')
2020-11-09 22:44:03 +00:00
# if this is a 'News' instance and we are viewing the features timeline
2020-11-10 15:12:07 +00:00
newsHeader = False
if defaultTimeline == 'tlfeatures':# and boxName == 'tlfeatures':
2020-11-10 15:12:07 +00:00
newsHeader = True
2020-11-13 21:26:45 +00:00
# Banner and "profile toggle" link
2020-11-09 22:44:03 +00:00
tlStr += '<div class="header">\n'
2020-11-13 21:26:45 +00:00
# TODO: This CSS should be moved out of the code
# Items like this that can be different per user should be kept
# in the user's folder and loaded as final CSS, to allow overwrite(s)
if not newsHeader:
tlStr += (f"\t<a class=\"timeline-banner hidden-text\" href=\"/users/{nickname}\" "
f"style=\"background-image: url('{usersPath}/{bannerFile}');\">"
f"{translate['Switch to profile view']}</a>\n")
else:
# TODO: News instances should ignore personalised banners
# Currently uses the 'news' actor banner - as it remains unchanged
tlStr += (f"\t<a class=\"timeline-banner hidden-text\" href=\"/users/{nickname}/tlfeatures\">"
f"{translate['Features']}</a>\n"
2020-11-24 14:07:38 +00:00
f"\t<div class=\"title\">\n"
f"\t\t<span>#IndymediaBack</span>\n"
f"\t</div>\n")
2020-11-10 15:12:07 +00:00
# TODO: Include '/editprofile' link on 'User' page for 'News' instances
2020-11-13 21:26:45 +00:00
2020-11-24 14:07:38 +00:00
# Certain Epciyon pages should only be accessible via the 'User' page for News instances
# TODO: The 'new...' pages appear to require handling elsewhere
2020-11-24 14:07:38 +00:00
userPages = ['inbox', 'outbox', 'dm', 'tlreplies', 'tlblogs', 'tlmedia', 'tlshares', \
'tlsaves', 'tlevents', 'tlbookmarks', 'moderation', 'search', \
'followers', 'newfollowers', 'newdm', 'newpost', 'newblog', 'newevent']
2020-11-24 14:07:38 +00:00
# Full row "navbar"
if defaultTimeline == 'tlfeatures':
# Show "tab" links instead of standard "buttons"
tlStr += headerNewsTabs(boxName, translate, usersPath, baseDir, userPages)
2020-11-24 14:07:38 +00:00
# Close banner div
tlStr += '</div>\n'
elif fullWidthTimelineButtonHeader:
2020-11-24 14:07:38 +00:00
# Close banner div
tlStr += '</div>\n'
2020-11-15 08:41:53 +00:00
tlStr += \
headerButtonsTimeline(defaultTimeline, boxName, pageNumber,
translate, usersPath,
minimal, moderator,
manuallyApproveFollowers,
baseDir, nickname,
domain, timelineStartTime,
iconsAsButtons, userPages)
else:
# Close banner div
tlStr += '</div>\n'
2020-11-10 15:12:07 +00:00
2020-12-03 11:41:10 +00:00
# TODO: Should probably use a more generic class, easier to re-use and help simplify CSS
# NOTE: Related also to class "page" added to 'webapp_create_post.py'
2020-11-10 15:12:07 +00:00
# start the timeline
2020-11-12 07:55:13 +00:00
tlStr += '<div class="timeline">\n'
2020-11-10 15:12:07 +00:00
2020-12-16 11:19:16 +00:00
domainFull = getFullDomain(domain, port)
2020-11-10 15:12:07 +00:00
# For 'News' instances, only show standard "buttons" on "user" pages
if defaultTimeline == 'tlfeatures' and boxName in userPages:
2020-11-24 14:07:38 +00:00
tlStr += \
headerButtonsTimeline(defaultTimeline, boxName, pageNumber,
translate, usersPath,
minimal, moderator,
manuallyApproveFollowers,
baseDir, nickname,
domain, timelineStartTime,
iconsAsButtons, userPages)
else:
# left column
leftColumnStr = \
getLeftColumnContent(baseDir, nickname, domainFull,
httpPrefix, translate, iconsPath,
editor, False, None, rssIconAtTop,
True, False)
tlStr += ' <div class="section links">\n' + \
leftColumnStr + ' </div>\n'
2020-11-10 15:12:07 +00:00
# center column containing posts
tlStr += ' <div class="section main">\n'
2020-11-10 15:12:07 +00:00
if not defaultTimeline == 'tlfeatures' and not fullWidthTimelineButtonHeader:
2020-11-15 08:41:53 +00:00
tlStr += \
headerButtonsTimeline(defaultTimeline, boxName, pageNumber,
translate, usersPath,
minimal, moderator,
manuallyApproveFollowers,
baseDir, nickname,
domain, timelineStartTime,
iconsAsButtons, userPages)
2020-11-15 08:41:53 +00:00
2020-11-10 15:12:07 +00:00
# second row of buttons for moderator actions
if moderator and boxName == 'moderation':
2020-11-09 22:44:03 +00:00
tlStr += \
2020-11-10 15:12:07 +00:00
'<form method="POST" action="/users/' + \
nickname + '/moderationaction">'
tlStr += '<div class="container">\n'
idx = 'Nickname or URL. Block using *@domain or nickname@domain'
2020-11-09 22:44:03 +00:00
tlStr += \
2020-11-10 15:12:07 +00:00
' <b>' + translate[idx] + '</b><br>\n'
2020-12-09 23:30:15 +00:00
if moderationActionStr:
tlStr += ' <input type="text" ' + \
'name="moderationAction" value="' + \
moderationActionStr + '" autofocus><br>\n'
else:
tlStr += ' <input type="text" ' + \
'name="moderationAction" value="" autofocus><br>\n'
2020-12-19 11:23:22 +00:00
2020-12-16 17:51:23 +00:00
tlStr += \
' <input type="submit" title="' + \
translate['Information about current blocks/suspensions'] + \
'" name="submitInfo" value="' + translate['Info'] + '">\n'
2020-11-09 22:44:03 +00:00
tlStr += \
2020-11-10 15:12:07 +00:00
' <input type="submit" title="' + \
translate['Remove the above item'] + \
'" name="submitRemove" value="' + \
translate['Remove'] + '">\n'
2020-12-19 11:23:22 +00:00
2020-11-10 15:12:07 +00:00
tlStr += \
' <input type="submit" title="' + \
translate['Suspend the above account nickname'] + \
'" name="submitSuspend" value="' + translate['Suspend'] + '">\n'
tlStr += \
' <input type="submit" title="' + \
translate['Remove a suspension for an account nickname'] + \
'" name="submitUnsuspend" value="' + \
translate['Unsuspend'] + '">\n'
2020-12-19 11:23:22 +00:00
2020-11-10 15:12:07 +00:00
tlStr += \
' <input type="submit" title="' + \
translate['Block an account on another instance'] + \
'" name="submitBlock" value="' + translate['Block'] + '">\n'
tlStr += \
' <input type="submit" title="' + \
translate['Unblock an account on another instance'] + \
'" name="submitUnblock" value="' + translate['Unblock'] + '">\n'
2020-12-19 11:23:22 +00:00
tlStr += \
' <input type="submit" title="' + \
translate['Filter out words'] + \
'" name="submitFilter" value="' + translate['Filter'] + '">\n'
tlStr += \
' <input type="submit" title="' + \
translate['Unfilter words'] + \
'" name="submitUnfilter" value="' + translate['Unfilter'] + '">\n'
2020-11-10 15:12:07 +00:00
tlStr += '</div>\n</form>\n'
2020-11-09 22:44:03 +00:00
_logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '6')
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
if boxName == 'tlshares':
maxSharesPerAccount = itemsPerPage
return (tlStr +
_htmlSharesTimeline(translate, pageNumber, itemsPerPage,
baseDir, actor, nickname, domain, port,
maxSharesPerAccount, httpPrefix) +
2020-11-10 15:12:07 +00:00
htmlFooter())
2020-11-09 22:44:03 +00:00
_logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '7')
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
# page up arrow
if pageNumber > 1:
tlStr += \
' <center>\n' + \
' <a href="' + usersPath + '/' + boxName + \
'?page=' + str(pageNumber - 1) + \
'"><img loading="lazy" class="pageicon" src="/' + \
2020-12-09 13:08:26 +00:00
'icons/pageup.png" title="' + \
2020-11-10 15:12:07 +00:00
translate['Page up'] + '" alt="' + \
translate['Page up'] + '"></a>\n' + \
' </center>\n'
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
# show the posts
itemCtr = 0
if timelineJson:
# if this is the media timeline then add an extra gallery container
if boxName == 'tlmedia':
if pageNumber > 1:
tlStr += '<br>'
tlStr += '<div class="galleryContainer">\n'
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
# show each post in the timeline
for item in timelineJson['orderedItems']:
if item['type'] == 'Create' or \
item['type'] == 'Announce' or \
item['type'] == 'Update':
# is the actor who sent this post snoozed?
if isPersonSnoozed(baseDir, nickname, domain, item['actor']):
continue
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
# is the post in the memory cache of recent ones?
currTlStr = None
if boxName != 'tlmedia' and \
recentPostsCache.get('index'):
postId = \
removeIdEnding(item['id']).replace('/', '#')
if postId in recentPostsCache['index']:
if not item.get('muted'):
if recentPostsCache['html'].get(postId):
currTlStr = recentPostsCache['html'][postId]
currTlStr = \
preparePostFromHtmlCache(currTlStr,
boxName,
pageNumber)
_logTimelineTiming(enableTimingLog,
timelineStartTime,
boxName, '10')
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
if not currTlStr:
_logTimelineTiming(enableTimingLog,
timelineStartTime,
boxName, '11')
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
# read the post from disk
currTlStr = \
individualPostAsHtml(False, recentPostsCache,
maxRecentPosts,
2020-12-09 13:31:54 +00:00
translate, pageNumber,
baseDir, session,
cachedWebfingers,
2020-11-10 15:12:07 +00:00
personCache,
nickname, domain, port,
2020-11-10 15:12:07 +00:00
item, None, True,
allowDeletion,
httpPrefix, projectVersion,
boxName,
2020-11-10 15:12:07 +00:00
YTReplacementDomain,
showPublishedDateOnly,
2020-12-23 23:59:49 +00:00
peertubeInstances,
2020-11-10 15:12:07 +00:00
boxName != 'dm',
showIndividualPostIcons,
manuallyApproveFollowers,
False, True)
_logTimelineTiming(enableTimingLog,
timelineStartTime, boxName, '12')
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
if currTlStr:
itemCtr += 1
2020-11-18 19:28:33 +00:00
tlStr += currTlStr
2020-11-10 15:12:07 +00:00
if separatorStr:
tlStr += separatorStr
if boxName == 'tlmedia':
tlStr += '</div>\n'
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
# page down arrow
if itemCtr > 2:
tlStr += \
' <center>\n' + \
' <a href="' + usersPath + '/' + boxName + '?page=' + \
str(pageNumber + 1) + \
'"><img loading="lazy" class="pageicon" src="/' + \
2020-12-09 13:08:26 +00:00
'icons/pagedown.png" title="' + \
2020-11-10 15:12:07 +00:00
translate['Page down'] + '" alt="' + \
translate['Page down'] + '"></a>\n' + \
' </center>\n'
2020-11-18 18:22:05 +00:00
# end of timeline-posts
tlStr += ' </div>\n'
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
# end of column-center
2020-11-12 07:55:13 +00:00
tlStr += ' </div>\n'
2020-11-10 15:12:07 +00:00
if defaultTimeline == 'tlfeatures' and boxName not in userPages:
2020-11-24 14:07:38 +00:00
# right column
rightColumnStr = getRightColumnContent(baseDir, nickname, domainFull,
httpPrefix, translate, iconsPath,
moderator, editor,
newswire, positiveVoting,
False, None, True,
showPublishAsIcon,
rssIconAtTop, publishButtonAtTop,
authorized, True)
tlStr += ' <div class="section newswire">' + \
rightColumnStr + ' </div>\n'
2020-11-10 15:12:07 +00:00
_logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '9')
2020-11-09 22:44:03 +00:00
2020-11-12 07:55:13 +00:00
tlStr += '</div>\n'
2020-11-10 15:12:07 +00:00
tlStr += htmlFooter()
return tlStr
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
def htmlIndividualShare(actor: str, item: {}, translate: {},
showContact: bool, removeButton: bool) -> str:
"""Returns an individual shared item as html
"""
profileStr = '<div class="container">\n'
profileStr += '<p class="share-title">' + item['displayName'] + '</p>\n'
if item.get('imageUrl'):
profileStr += '<a href="' + item['imageUrl'] + '">\n'
profileStr += \
'<img loading="lazy" src="' + item['imageUrl'] + \
'" alt="' + translate['Item image'] + '">\n</a>\n'
profileStr += '<p>' + item['summary'] + '</p>\n'
profileStr += \
'<p><b>' + translate['Type'] + ':</b> ' + item['itemType'] + ' '
profileStr += \
'<b>' + translate['Category'] + ':</b> ' + item['category'] + ' '
profileStr += \
'<b>' + translate['Location'] + ':</b> ' + item['location'] + '</p>\n'
sharedesc = item['displayName']
if '<' not in sharedesc and '?' not in sharedesc:
if showContact:
contactActor = item['actor']
profileStr += \
'<p><a href="' + actor + \
'?replydm=sharedesc:' + sharedesc + \
'?mention=' + contactActor + '"><button class="button">' + \
translate['Contact'] + '</button></a>\n'
if removeButton:
profileStr += \
' <a href="' + actor + '?rmshare=' + sharedesc + \
'"><button class="button">' + \
translate['Remove'] + '</button></a>\n'
2020-11-10 15:12:07 +00:00
profileStr += '</div>\n'
return profileStr
2020-11-09 22:44:03 +00:00
def _htmlSharesTimeline(translate: {}, pageNumber: int, itemsPerPage: int,
baseDir: str, actor: str,
nickname: str, domain: str, port: int,
maxSharesPerAccount: int, httpPrefix: str) -> str:
2020-11-10 15:12:07 +00:00
"""Show shared items timeline as html
"""
sharesJson, lastPage = \
sharesTimelineJson(actor, pageNumber, itemsPerPage,
baseDir, maxSharesPerAccount)
2020-12-16 11:19:16 +00:00
domainFull = getFullDomain(domain, port)
2020-11-10 15:12:07 +00:00
actor = httpPrefix + '://' + domainFull + '/users/' + nickname
timelineStr = ''
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
if pageNumber > 1:
timelineStr += \
' <center>\n' + \
' <a href="' + actor + '/tlshares?page=' + \
str(pageNumber - 1) + \
'"><img loading="lazy" class="pageicon" src="/' + \
2020-12-09 13:08:26 +00:00
'icons/pageup.png" title="' + translate['Page up'] + \
2020-11-10 15:12:07 +00:00
'" alt="' + translate['Page up'] + '"></a>\n' + \
' </center>\n'
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
separatorStr = htmlPostSeparator(baseDir, None)
for published, item in sharesJson.items():
showContactButton = False
if item['actor'] != actor:
showContactButton = True
showRemoveButton = False
if item['actor'] == actor:
showRemoveButton = True
2020-11-18 19:28:33 +00:00
timelineStr += \
2020-11-10 15:12:07 +00:00
htmlIndividualShare(actor, item, translate,
showContactButton, showRemoveButton)
2020-11-18 19:28:33 +00:00
timelineStr += separatorStr
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
if not lastPage:
timelineStr += \
' <center>\n' + \
' <a href="' + actor + '/tlshares?page=' + \
str(pageNumber + 1) + \
'"><img loading="lazy" class="pageicon" src="/' + \
2020-12-09 13:08:26 +00:00
'icons/pagedown.png" title="' + translate['Page down'] + \
2020-11-10 15:12:07 +00:00
'" alt="' + translate['Page down'] + '"></a>\n' + \
' </center>\n'
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
return timelineStr
2020-11-09 22:44:03 +00:00
2020-11-13 21:26:45 +00:00
# TODO: Can this be re-implemented as injecting an additional CSS class ?
# Would allow for much more opportunity to style
def htmlHighlightLabel(label: str, highlight: bool) -> str:
"""If the give text should be highlighted then return
the appropriate markup.
This is so that in shell browsers, like lynx, it's possible
to see if the replies or DM button are highlighted.
"""
if not highlight:
return label
return '*' + str(label) + '*'
def headerButtonsTimeline(defaultTimeline: str,
boxName: str,
pageNumber: int,
translate: {},
usersPath: str,
minimal: bool,
moderator: bool,
manuallyApproveFollowers: bool,
baseDir: str,
nickname: str, domain: str,
timelineStartTime,
iconsAsButtons: bool) -> str:
"""Returns the header at the top of the timeline, containing
buttons for inbox, outbox, search, calendar, etc
"""
accountDir = baseDir + '/accounts/' + nickname + '@' + domain
# should the calendar icon be highlighted?
newCalendarEvent = False
calendarImage = 'calendar.png'
calendarPath = '/calendar'
calendarFile = accountDir + '/.newCalendar'
if os.path.isfile(calendarFile):
newCalendarEvent = True
calendarImage = 'calendar_notify.png'
with open(calendarFile, 'r') as calfile:
calendarPath = calfile.read().replace('##sent##', '')
calendarPath = calendarPath.replace('\n', '').replace('\r', '')
# should the DM button be highlighted?
newDM = False
dmFile = accountDir + '/.newDM'
if os.path.isfile(dmFile):
newDM = True
if boxName == 'dm':
os.remove(dmFile)
# should the Replies button be highlighted?
newReply = False
replyFile = accountDir + '/.newReply'
if os.path.isfile(replyFile):
newReply = True
if boxName == 'tlreplies':
os.remove(replyFile)
# should the Shares button be highlighted?
newShare = False
newShareFile = accountDir + '/.newShare'
if os.path.isfile(newShareFile):
newShare = True
if boxName == 'tlshares':
os.remove(newShareFile)
# should the Moderation/reports button be highlighted?
newReport = False
newReportFile = accountDir + '/.newReport'
if os.path.isfile(newReportFile):
newReport = True
if boxName == 'moderation':
os.remove(newReportFile)
# start of the button header with inbox, outbox, etc
# TODO: [rename] containerHeader -> menu (or similar)
tlStr = '\t<div class="containerHeader">\n'
2020-11-13 21:26:45 +00:00
2020-11-13 21:26:45 +00:00
# TODO: Group _all_ items that are hidden in 'minimal' mode ?
# - Are there others elsewhere in the code ?
# All menu items default to text buttons
# Add class "icon-button" to overwrite default behaviour
# NOTE: Currently handled further down in loops over navButtonList and actionButtonList
2020-11-13 21:26:45 +00:00
# Menu buttons are split into two sections
# - Navigation buttons : Informational pages, e.g. Inbox
# - Action buttons : More clear action, e.g. Search, Create Post
# default appearance text; use CSS class(es) to re-style
2020-11-13 21:26:45 +00:00
# A list of buttons to be rendered as html,
# each item being a tuple containing
# - ref name
# - dictionary of unique config
2020-11-13 21:26:45 +00:00
# Each dict has:
# - pageRef : the url snippet
# - translationText : text to be displayed
# - highlightLabel : boolean to determine highlight
# - isIcon : boolean to trigger specific CSS class addition(s) for icon buttons
# - class : string of class(es) to append
# - iconClass : string of class(es) to append, only regarding icons
# Buttons should be added in the order you wish them to appear in the menu
navButtonList = []
actionButtonList = []
# Too many buttons - some visibility can be toggled
# TODO: Show/Hide menu buttons should not require page reload!
# Implement checkbox method
# Requires grouping the buttons that are shown/hidden ?
# TODO: The 'minimal' attribute could be done using CSS class ?
# Minimal View only shows:
# - Inbox
# - Outbox
# - DM
# - Replies
# - News # TODO: Should this be in minimal view? 'Media' and 'Blogs' are not ...
2020-11-13 21:26:45 +00:00
# NOTE: "Action" buttons (icons in default Epicyon) are always visible
navButtonList.append(('inbox',
{'pageRef': '/inbox',
'translateText': 'Inbox'}
))
navButtonList.append(('outbox',
{'pageRef': '/outbox',
'translateText': 'Outbox'}
))
navButtonList.append(('dm',
{'pageRef': '/dm',
'translateText': 'DM',
'highlightLabel': newDM}
))
navButtonList.append(('tlreplies',
{'pageRef': '/tlreplies',
'translateText': 'Replies',
'highlightLabel': newReply}
))
if not minimal:
navButtonList.append(('tlnews',
{'pageRef': '/tlnews',
'translateText': 'News'}
))
# The following translationText should be 'Article' for News instances
navButtonList.append(('tlblogs',
{'pageRef': '/tlblogs',
'translateText': 'Blogs'}
))
navButtonList.append(('tlmedia',
{'pageRef': '/tlmedia',
'translateText': 'Media'}
))
navButtonList.append(('tlshares',
{'pageRef': '/tlshares',
'translateText': 'Shares',
'highlightLabel': newShare}
))
navButtonList.append(('tlbookmarks',
{'pageRef': '/tlbookmarks',
'translateText': 'Bookmarks'}
))
navButtonList.append(('tlevents',
{'pageRef': '/tlevents',
'translateText': 'Events'}
))
if moderator:
navButtonList.append(('moderation',
{'pageRef': '/moderation',
'translateText': 'Mod',
'highlightLabel': newReport}
))
# Single out the "instance-type" button, and move to front of list
# NOTE: Current instance types are: 'tlblogs', 'tlmedia', 'tlnews'
for i, (name, config) in enumerate(navButtonList):
if name == defaultTimeline:
tmp = navButtonList.pop(i)
navButtonList.insert(0, tmp)
break
# Generate HTML list
navButtonStr = '\t\t<div class="navbuttons">\n'
navButtonStr += '\t\t\t<ul class="button-bar">\n'
2020-11-13 21:26:45 +00:00
for name, config in navButtonList:
classStr = 'button-test'
textStr = ''
if 'class' in config:
classStr += ' ' + config['class']
if 'highlightLabel' in config and config['highlightLabel']:
if name == boxName:
classStr += ' button-test-selected-highlighted'
else:
classStr += ' button-test-highlighted'
# TODO: Replace 'config' dereference with 'True' as it always will be by this point ?
textStr = htmlHighlightLabel(translate[config['translateText']], \
config['highlightLabel'])
else:
if name == boxName:
classStr += ' button-test-selected'
textStr += translate[config['translateText']]
navButtonStr += (f"\t\t\t\t<a class=\"{classStr}\" href=\"{usersPath}{config['pageRef']}\">\n"
f'\t\t\t\t\t<li>{textStr}</li>\n'
f'\t\t\t\t</a>\n')
navButtonStr += '\t\t\t</ul>\n\t\t</div>\n'
2020-11-13 21:26:45 +00:00
# start of headericons list
# show an icon for new follow approvals
followApprovals = False
followRequestsFilename = \
baseDir + '/accounts/' + \
nickname + '@' + domain + '/followrequests.txt'
if os.path.isfile(followRequestsFilename):
with open(followRequestsFilename, 'r') as f:
for line in f:
if len(line) > 0:
# show follow approvals icon
followApprovals = True
break
# NOTE: Certain buttons only appear when relevant
# TODO: Determine if approvals (currently appended at end of actionButtonList)
# and events should be in a separate list;
# e.g. notificationButtonList
# Having its' own <div> for instance would allow more versatile styling
2020-11-13 21:26:45 +00:00
if followApprovals:
actionButtonList.append(('followers',
{'pageRef': '/followers',
'translateText': 'Approve follow requests',
'iconClass': 'icon-newfollow'}
))
# Only show todays events buttons on the first inbox page
if boxName == 'inbox' and pageNumber == 1:
if todaysEventsCheck(baseDir, nickname, domain):
now = datetime.now()
todayRef = '/calendar?year=' + str(now.year) + \
'?month=' + str(now.month) + \
'?day=' + str(now.day)
actionButtonList.append(('today-event',
{'pageRef': todayRef,
'translateText': 'Happening Today',
'class': 'button-event'}
))
if thisWeeksEventsCheck(baseDir, nickname, domain):
actionButtonList.append(('week-event',
{'pageRef': '/calendar',
'translateText': 'Happening Today',
'class': 'button-event'}
))
# NOTE: CSS used to show or hide these based on screen size
actionButtonList.append(('newswire',
{'pageRef': '/newswiremobile',
'translateText': 'Newswire',
'class': 'mobile-only',
'iconClass': 'icon-newswire'}
))
actionButtonList.append(('links',
{'pageRef': '/linksmobile',
'translateText': 'Edit Links',
'class': 'mobile-only',
'iconClass': 'icon-links'}
))
2020-11-13 21:26:45 +00:00
# what screen to go to when a new post is created
# The following produces one button/icon for "new post" dependent on current viewed page
if boxName == 'dm':
actionButtonList.append(('newdm',
{'pageRef': '/newdm',
'translateText': 'Create a new DM'}
))
elif boxName == 'tlblogs' or boxName == 'tlnews':
actionButtonList.append(('newblog',
{'pageRef': '/newblog',
'translateText': 'Create a new post'}
))
elif boxName == 'tlevents':
actionButtonList.append(('newevent',
{'pageRef': '/newevent',
'translateText': 'Create a new event'}
))
else:
if not manuallyApproveFollowers:
actionButtonList.append(('newpost',
{'pageRef': '/newpost',
'translateText': 'Create a new post'}
))
else:
actionButtonList.append(('newfollowers',
{'pageRef': '/newfollowers',
'translateText': 'Create a new post'}
))
# 'icon-<type>' is solely used for the CSS to load appropriate icon
actionButtonList[-1][1]['iconClass'] = 'icon-newpost'
actionButtonList.append(('calendar',
{'pageRef': calendarPath,
'translateText': 'Calendar',
'iconClass': 'icon-calendar'}
))
actionButtonList.append(('search',
{'pageRef': '/search',
'translateText': 'Search',
'iconClass': 'icon-search'}
))
actionButtonList.append(('minimal',
{'pageRef': '/minimal',
'translateText': 'Show/Hide Buttons',
'iconClass': 'icon-showhide'}
))
actionButtonStr = '\t\t<div class="actionbuttons">\n'
actionButtonStr += '\t\t\t<ul class="button-bar">\n'
2020-11-13 21:26:45 +00:00
# TODO: [rename] 'timelineicon' should maybe be more generic, e.g 'icon-button'
# Generate HTML list
for name, config in actionButtonList:
if iconsAsButtons:
classStr = 'button-test'
else:
# Currently 'timelineicon' denotes an icon instead of text button
classStr = 'timelineicon'
# NOTE: If iconClass is missing, expect some kind of failed output
# CSS alone is responsible for what image will be displayed, etc
if 'iconClass' in config:
classStr += ' ' + config['iconClass']
if 'class' in config:
classStr += ' ' + config['class']
if 'highlightLabel' in config:
textStr = htmlHighlightLabel(translate[config['translateText']], config['highlightLabel'])
2020-11-13 21:26:45 +00:00
else:
textStr = translate[config['translateText']]
actionButtonStr += (f"\t\t\t\t<a class=\"{classStr}\" href=\"{usersPath}{config['pageRef']}\">\n"
f'\t\t\t\t\t<li>{textStr}</li>\n'
f'\t\t\t\t</a>\n')
2020-11-13 21:26:45 +00:00
actionButtonStr += '\t\t\t</ul>\n\t\t</div>\n'
2020-11-13 21:26:45 +00:00
# benchmark 5
timeDiff = int((time.time() - timelineStartTime) * 1000)
if timeDiff > 100:
print('TIMELINE TIMING ' + boxName + ' 5 = ' + str(timeDiff))
# Compile HTML parts
tlStr += navButtonStr + actionButtonStr
2020-11-13 21:26:45 +00:00
# End header button section
tlStr += '\t</div>\n'
2020-11-13 21:26:45 +00:00
return tlStr
def headerNewsTabs(boxName: str,
translate: {},
usersPath: str,
moderator: bool,
baseDir: str) -> str:
navTabList = []
navTabList.append(('tlnews',
{'pageRef': '/tlnews',
'translateText': 'Features'}
))
navTabList.append(('newswiremobile',
{'pageRef': '/newswiremobile',
'translateText': 'News'}
))
navTabList.append(('calendar',
{'pageRef': '/calendar',
'translateText': 'Calendar'}
))
navTabList.append(('linksmobile',
{'pageRef': '/linksmobile',
'translateText': 'Links'}
))
navTabList.append(('inbox',
{'pageRef': '/inbox',
'translateText': 'User'}
))
navStr = '\t\t<div class="navtabs">\n'
navStr += '\t\t\t<ul>\n'
for name, config in navTabList:
classStr = ''
if name == boxName:
classStr = 'tab-highlight'
if 'class' in config:
classStr += ' ' + config['class']
textStr = translate[config['translateText']]
navStr += (f"\t\t\t\t<a class=\"{classStr}\" href=\"{usersPath}{config['pageRef']}\">\n"
f'\t\t\t\t\t<li>{textStr}</li>\n'
f'\t\t\t\t</a>\n')
navStr += '\t\t\t</ul>\n\t\t</div>\n'
return navStr
2020-11-09 22:44:03 +00:00
def htmlShares(cssCache: {}, defaultTimeline: str,
recentPostsCache: {}, maxRecentPosts: int,
translate: {}, pageNumber: int, itemsPerPage: int,
session, baseDir: str,
cachedWebfingers: {}, personCache: {},
2020-11-09 22:44:03 +00:00
nickname: str, domain: str, port: int,
allowDeletion: bool,
httpPrefix: str, projectVersion: str,
YTReplacementDomain: str,
showPublishedDateOnly: bool,
newswire: {}, positiveVoting: bool,
showPublishAsIcon: bool,
fullWidthTimelineButtonHeader: bool,
iconsAsButtons: bool,
rssIconAtTop: bool,
publishButtonAtTop: bool,
2020-12-23 23:59:49 +00:00
authorized: bool, theme: str,
peertubeInstances: []) -> str:
2020-11-09 22:44:03 +00:00
"""Show the shares timeline as html
"""
manuallyApproveFollowers = \
followerApprovalActive(baseDir, nickname, domain)
return htmlTimeline(cssCache, defaultTimeline,
recentPostsCache, maxRecentPosts,
translate, pageNumber,
itemsPerPage, session, baseDir,
cachedWebfingers, personCache,
2020-11-09 22:44:03 +00:00
nickname, domain, port, None,
'tlshares', allowDeletion,
httpPrefix, projectVersion, manuallyApproveFollowers,
False, YTReplacementDomain,
showPublishedDateOnly,
newswire, False, False,
positiveVoting, showPublishAsIcon,
fullWidthTimelineButtonHeader,
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
2020-12-23 23:59:49 +00:00
authorized, None, theme, peertubeInstances)
2020-11-09 22:44:03 +00:00
def htmlInbox(cssCache: {}, defaultTimeline: str,
recentPostsCache: {}, maxRecentPosts: int,
translate: {}, pageNumber: int, itemsPerPage: int,
session, baseDir: str,
cachedWebfingers: {}, personCache: {},
2020-11-09 22:44:03 +00:00
nickname: str, domain: str, port: int, inboxJson: {},
allowDeletion: bool,
httpPrefix: str, projectVersion: str,
minimal: bool, YTReplacementDomain: str,
showPublishedDateOnly: bool,
newswire: {}, positiveVoting: bool,
showPublishAsIcon: bool,
fullWidthTimelineButtonHeader: bool,
iconsAsButtons: bool,
rssIconAtTop: bool,
publishButtonAtTop: bool,
2020-12-23 23:59:49 +00:00
authorized: bool, theme: str,
peertubeInstances: []) -> str:
2020-11-09 22:44:03 +00:00
"""Show the inbox as html
"""
manuallyApproveFollowers = \
followerApprovalActive(baseDir, nickname, domain)
return htmlTimeline(cssCache, defaultTimeline,
recentPostsCache, maxRecentPosts,
translate, pageNumber,
itemsPerPage, session, baseDir,
cachedWebfingers, personCache,
2020-11-09 22:44:03 +00:00
nickname, domain, port, inboxJson,
'inbox', allowDeletion,
httpPrefix, projectVersion, manuallyApproveFollowers,
minimal, YTReplacementDomain,
showPublishedDateOnly,
newswire, False, False,
positiveVoting, showPublishAsIcon,
fullWidthTimelineButtonHeader,
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
2020-12-23 23:59:49 +00:00
authorized, None, theme, peertubeInstances)
2020-11-09 22:44:03 +00:00
def htmlBookmarks(cssCache: {}, defaultTimeline: str,
recentPostsCache: {}, maxRecentPosts: int,
translate: {}, pageNumber: int, itemsPerPage: int,
session, baseDir: str,
cachedWebfingers: {}, personCache: {},
2020-11-09 22:44:03 +00:00
nickname: str, domain: str, port: int, bookmarksJson: {},
allowDeletion: bool,
httpPrefix: str, projectVersion: str,
minimal: bool, YTReplacementDomain: str,
showPublishedDateOnly: bool,
newswire: {}, positiveVoting: bool,
showPublishAsIcon: bool,
fullWidthTimelineButtonHeader: bool,
iconsAsButtons: bool,
rssIconAtTop: bool,
publishButtonAtTop: bool,
2020-12-23 23:59:49 +00:00
authorized: bool, theme: str,
peertubeInstances: []) -> str:
2020-11-09 22:44:03 +00:00
"""Show the bookmarks as html
"""
manuallyApproveFollowers = \
followerApprovalActive(baseDir, nickname, domain)
return htmlTimeline(cssCache, defaultTimeline,
recentPostsCache, maxRecentPosts,
translate, pageNumber,
itemsPerPage, session, baseDir,
cachedWebfingers, personCache,
2020-11-09 22:44:03 +00:00
nickname, domain, port, bookmarksJson,
'tlbookmarks', allowDeletion,
httpPrefix, projectVersion, manuallyApproveFollowers,
minimal, YTReplacementDomain,
showPublishedDateOnly,
newswire, False, False,
positiveVoting, showPublishAsIcon,
fullWidthTimelineButtonHeader,
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
2020-12-23 23:59:49 +00:00
authorized, None, theme, peertubeInstances)
2020-11-09 22:44:03 +00:00
def htmlEvents(cssCache: {}, defaultTimeline: str,
recentPostsCache: {}, maxRecentPosts: int,
translate: {}, pageNumber: int, itemsPerPage: int,
session, baseDir: str,
cachedWebfingers: {}, personCache: {},
2020-11-09 22:44:03 +00:00
nickname: str, domain: str, port: int, bookmarksJson: {},
allowDeletion: bool,
httpPrefix: str, projectVersion: str,
minimal: bool, YTReplacementDomain: str,
showPublishedDateOnly: bool,
newswire: {}, positiveVoting: bool,
showPublishAsIcon: bool,
fullWidthTimelineButtonHeader: bool,
iconsAsButtons: bool,
rssIconAtTop: bool,
publishButtonAtTop: bool,
2020-12-23 23:59:49 +00:00
authorized: bool, theme: str,
peertubeInstances: []) -> str:
2020-11-09 22:44:03 +00:00
"""Show the events as html
"""
manuallyApproveFollowers = \
followerApprovalActive(baseDir, nickname, domain)
return htmlTimeline(cssCache, defaultTimeline,
recentPostsCache, maxRecentPosts,
translate, pageNumber,
itemsPerPage, session, baseDir,
cachedWebfingers, personCache,
2020-11-09 22:44:03 +00:00
nickname, domain, port, bookmarksJson,
'tlevents', allowDeletion,
httpPrefix, projectVersion, manuallyApproveFollowers,
minimal, YTReplacementDomain,
showPublishedDateOnly,
newswire, False, False,
positiveVoting, showPublishAsIcon,
fullWidthTimelineButtonHeader,
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
2020-12-23 23:59:49 +00:00
authorized, None, theme, peertubeInstances)
2020-11-09 22:44:03 +00:00
def htmlInboxDMs(cssCache: {}, defaultTimeline: str,
recentPostsCache: {}, maxRecentPosts: int,
translate: {}, pageNumber: int, itemsPerPage: int,
session, baseDir: str,
cachedWebfingers: {}, personCache: {},
2020-11-09 22:44:03 +00:00
nickname: str, domain: str, port: int, inboxJson: {},
allowDeletion: bool,
httpPrefix: str, projectVersion: str,
minimal: bool, YTReplacementDomain: str,
showPublishedDateOnly: bool,
newswire: {}, positiveVoting: bool,
showPublishAsIcon: bool,
fullWidthTimelineButtonHeader: bool,
iconsAsButtons: bool,
rssIconAtTop: bool,
publishButtonAtTop: bool,
2020-12-23 23:59:49 +00:00
authorized: bool, theme: str,
peertubeInstances: []) -> str:
2020-11-09 22:44:03 +00:00
"""Show the DM timeline as html
"""
return htmlTimeline(cssCache, defaultTimeline,
recentPostsCache, maxRecentPosts,
translate, pageNumber,
itemsPerPage, session, baseDir,
cachedWebfingers, personCache,
2020-11-09 22:44:03 +00:00
nickname, domain, port, inboxJson, 'dm', allowDeletion,
httpPrefix, projectVersion, False, minimal,
YTReplacementDomain, showPublishedDateOnly,
newswire, False, False, positiveVoting,
showPublishAsIcon,
fullWidthTimelineButtonHeader,
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
2020-12-23 23:59:49 +00:00
authorized, None, theme, peertubeInstances)
2020-11-09 22:44:03 +00:00
def htmlInboxReplies(cssCache: {}, defaultTimeline: str,
recentPostsCache: {}, maxRecentPosts: int,
translate: {}, pageNumber: int, itemsPerPage: int,
session, baseDir: str,
cachedWebfingers: {}, personCache: {},
2020-11-09 22:44:03 +00:00
nickname: str, domain: str, port: int, inboxJson: {},
allowDeletion: bool,
httpPrefix: str, projectVersion: str,
minimal: bool, YTReplacementDomain: str,
showPublishedDateOnly: bool,
newswire: {}, positiveVoting: bool,
showPublishAsIcon: bool,
fullWidthTimelineButtonHeader: bool,
iconsAsButtons: bool,
rssIconAtTop: bool,
publishButtonAtTop: bool,
2020-12-23 23:59:49 +00:00
authorized: bool, theme: str,
peertubeInstances: []) -> str:
2020-11-09 22:44:03 +00:00
"""Show the replies timeline as html
"""
return htmlTimeline(cssCache, defaultTimeline,
recentPostsCache, maxRecentPosts,
translate, pageNumber,
itemsPerPage, session, baseDir,
cachedWebfingers, personCache,
2020-11-09 22:44:03 +00:00
nickname, domain, port, inboxJson, 'tlreplies',
allowDeletion, httpPrefix, projectVersion, False,
minimal, YTReplacementDomain,
showPublishedDateOnly,
newswire, False, False,
positiveVoting, showPublishAsIcon,
fullWidthTimelineButtonHeader,
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
2020-12-23 23:59:49 +00:00
authorized, None, theme, peertubeInstances)
2020-11-09 22:44:03 +00:00
def htmlInboxMedia(cssCache: {}, defaultTimeline: str,
recentPostsCache: {}, maxRecentPosts: int,
translate: {}, pageNumber: int, itemsPerPage: int,
session, baseDir: str,
cachedWebfingers: {}, personCache: {},
2020-11-09 22:44:03 +00:00
nickname: str, domain: str, port: int, inboxJson: {},
allowDeletion: bool,
httpPrefix: str, projectVersion: str,
minimal: bool, YTReplacementDomain: str,
showPublishedDateOnly: bool,
newswire: {}, positiveVoting: bool,
showPublishAsIcon: bool,
fullWidthTimelineButtonHeader: bool,
iconsAsButtons: bool,
rssIconAtTop: bool,
publishButtonAtTop: bool,
2020-12-23 23:59:49 +00:00
authorized: bool, theme: str,
peertubeInstances: []) -> str:
2020-11-09 22:44:03 +00:00
"""Show the media timeline as html
"""
return htmlTimeline(cssCache, defaultTimeline,
recentPostsCache, maxRecentPosts,
translate, pageNumber,
itemsPerPage, session, baseDir,
cachedWebfingers, personCache,
2020-11-09 22:44:03 +00:00
nickname, domain, port, inboxJson, 'tlmedia',
allowDeletion, httpPrefix, projectVersion, False,
minimal, YTReplacementDomain,
showPublishedDateOnly,
newswire, False, False,
positiveVoting, showPublishAsIcon,
fullWidthTimelineButtonHeader,
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
2020-12-23 23:59:49 +00:00
authorized, None, theme, peertubeInstances)
2020-11-09 22:44:03 +00:00
def htmlInboxBlogs(cssCache: {}, defaultTimeline: str,
recentPostsCache: {}, maxRecentPosts: int,
translate: {}, pageNumber: int, itemsPerPage: int,
session, baseDir: str,
cachedWebfingers: {}, personCache: {},
2020-11-09 22:44:03 +00:00
nickname: str, domain: str, port: int, inboxJson: {},
allowDeletion: bool,
httpPrefix: str, projectVersion: str,
minimal: bool, YTReplacementDomain: str,
showPublishedDateOnly: bool,
newswire: {}, positiveVoting: bool,
showPublishAsIcon: bool,
fullWidthTimelineButtonHeader: bool,
iconsAsButtons: bool,
rssIconAtTop: bool,
publishButtonAtTop: bool,
2020-12-23 23:59:49 +00:00
authorized: bool, theme: str,
peertubeInstances: []) -> str:
2020-11-09 22:44:03 +00:00
"""Show the blogs timeline as html
"""
return htmlTimeline(cssCache, defaultTimeline,
recentPostsCache, maxRecentPosts,
translate, pageNumber,
itemsPerPage, session, baseDir,
cachedWebfingers, personCache,
2020-11-09 22:44:03 +00:00
nickname, domain, port, inboxJson, 'tlblogs',
allowDeletion, httpPrefix, projectVersion, False,
minimal, YTReplacementDomain,
showPublishedDateOnly,
newswire, False, False,
positiveVoting, showPublishAsIcon,
fullWidthTimelineButtonHeader,
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
2020-12-23 23:59:49 +00:00
authorized, None, theme, peertubeInstances)
2020-11-09 22:44:03 +00:00
2020-11-27 11:22:47 +00:00
def htmlInboxFeatures(cssCache: {}, defaultTimeline: str,
recentPostsCache: {}, maxRecentPosts: int,
translate: {}, pageNumber: int, itemsPerPage: int,
session, baseDir: str,
cachedWebfingers: {}, personCache: {},
2020-11-27 11:22:47 +00:00
nickname: str, domain: str, port: int, inboxJson: {},
allowDeletion: bool,
httpPrefix: str, projectVersion: str,
minimal: bool, YTReplacementDomain: str,
showPublishedDateOnly: bool,
newswire: {}, positiveVoting: bool,
showPublishAsIcon: bool,
fullWidthTimelineButtonHeader: bool,
iconsAsButtons: bool,
rssIconAtTop: bool,
publishButtonAtTop: bool,
2020-12-20 17:26:38 +00:00
authorized: bool,
2020-12-23 23:59:49 +00:00
theme: str,
peertubeInstances: []) -> str:
2020-11-27 11:22:47 +00:00
"""Show the features timeline as html
"""
return htmlTimeline(cssCache, defaultTimeline,
recentPostsCache, maxRecentPosts,
translate, pageNumber,
itemsPerPage, session, baseDir,
cachedWebfingers, personCache,
2020-11-27 15:05:22 +00:00
nickname, domain, port, inboxJson, 'tlfeatures',
2020-11-27 11:22:47 +00:00
allowDeletion, httpPrefix, projectVersion, False,
minimal, YTReplacementDomain,
showPublishedDateOnly,
newswire, False, False,
positiveVoting, showPublishAsIcon,
fullWidthTimelineButtonHeader,
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
2020-12-23 23:59:49 +00:00
authorized, None, theme, peertubeInstances)
2020-11-27 11:22:47 +00:00
2020-11-09 22:44:03 +00:00
def htmlInboxNews(cssCache: {}, defaultTimeline: str,
recentPostsCache: {}, maxRecentPosts: int,
translate: {}, pageNumber: int, itemsPerPage: int,
session, baseDir: str,
cachedWebfingers: {}, personCache: {},
2020-11-09 22:44:03 +00:00
nickname: str, domain: str, port: int, inboxJson: {},
allowDeletion: bool,
httpPrefix: str, projectVersion: str,
minimal: bool, YTReplacementDomain: str,
showPublishedDateOnly: bool,
newswire: {}, moderator: bool, editor: bool,
positiveVoting: bool, showPublishAsIcon: bool,
fullWidthTimelineButtonHeader: bool,
iconsAsButtons: bool,
rssIconAtTop: bool,
publishButtonAtTop: bool,
2020-12-23 23:59:49 +00:00
authorized: bool, theme: str,
peertubeInstances: []) -> str:
2020-11-09 22:44:03 +00:00
"""Show the news timeline as html
"""
return htmlTimeline(cssCache, defaultTimeline,
recentPostsCache, maxRecentPosts,
translate, pageNumber,
itemsPerPage, session, baseDir,
cachedWebfingers, personCache,
2020-11-09 22:44:03 +00:00
nickname, domain, port, inboxJson, 'tlnews',
allowDeletion, httpPrefix, projectVersion, False,
minimal, YTReplacementDomain,
showPublishedDateOnly,
newswire, moderator, editor,
positiveVoting, showPublishAsIcon,
fullWidthTimelineButtonHeader,
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
2020-12-23 23:59:49 +00:00
authorized, None, theme, peertubeInstances)
2020-11-09 22:44:03 +00:00
def htmlOutbox(cssCache: {}, defaultTimeline: str,
recentPostsCache: {}, maxRecentPosts: int,
translate: {}, pageNumber: int, itemsPerPage: int,
session, baseDir: str,
cachedWebfingers: {}, personCache: {},
2020-11-09 22:44:03 +00:00
nickname: str, domain: str, port: int, outboxJson: {},
allowDeletion: bool,
httpPrefix: str, projectVersion: str,
minimal: bool, YTReplacementDomain: str,
showPublishedDateOnly: bool,
newswire: {}, positiveVoting: bool,
showPublishAsIcon: bool,
fullWidthTimelineButtonHeader: bool,
iconsAsButtons: bool,
rssIconAtTop: bool,
publishButtonAtTop: bool,
2020-12-23 23:59:49 +00:00
authorized: bool, theme: str,
peertubeInstances: []) -> str:
2020-11-09 22:44:03 +00:00
"""Show the Outbox as html
"""
manuallyApproveFollowers = \
followerApprovalActive(baseDir, nickname, domain)
return htmlTimeline(cssCache, defaultTimeline,
recentPostsCache, maxRecentPosts,
translate, pageNumber,
itemsPerPage, session, baseDir,
cachedWebfingers, personCache,
2020-11-09 22:44:03 +00:00
nickname, domain, port, outboxJson, 'outbox',
allowDeletion, httpPrefix, projectVersion,
manuallyApproveFollowers, minimal,
YTReplacementDomain, showPublishedDateOnly,
newswire, False, False, positiveVoting,
showPublishAsIcon, fullWidthTimelineButtonHeader,
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
2020-12-23 23:59:49 +00:00
authorized, None, theme, peertubeInstances)