forked from indymedia/epicyon
Simplify nav button creation logic
parent
e44dbc2497
commit
45c5ff0924
|
@ -69,51 +69,9 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
||||||
|
|
||||||
timelineStartTime = time.time()
|
timelineStartTime = time.time()
|
||||||
|
|
||||||
accountDir = baseDir + '/accounts/' + nickname + '@' + domain
|
# directory where icons are found
|
||||||
|
# This changes depending upon theme
|
||||||
# should the calendar icon be highlighted?
|
iconsDir = getIconsDir(baseDir)
|
||||||
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)
|
|
||||||
|
|
||||||
separatorStr = ''
|
separatorStr = ''
|
||||||
if boxName != 'tlmedia':
|
if boxName != 'tlmedia':
|
||||||
|
@ -140,60 +98,6 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
||||||
|
|
||||||
_logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '2')
|
_logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '2')
|
||||||
|
|
||||||
# the appearance of buttons - highlighted or not
|
|
||||||
inboxButton = 'button'
|
|
||||||
blogsButton = 'button'
|
|
||||||
featuresButton = 'button'
|
|
||||||
newsButton = 'button'
|
|
||||||
dmButton = 'button'
|
|
||||||
if newDM:
|
|
||||||
dmButton = 'buttonhighlighted'
|
|
||||||
repliesButton = 'button'
|
|
||||||
if newReply:
|
|
||||||
repliesButton = 'buttonhighlighted'
|
|
||||||
mediaButton = 'button'
|
|
||||||
bookmarksButton = 'button'
|
|
||||||
eventsButton = 'button'
|
|
||||||
sentButton = 'button'
|
|
||||||
sharesButton = 'button'
|
|
||||||
if newShare:
|
|
||||||
sharesButton = 'buttonhighlighted'
|
|
||||||
moderationButton = 'button'
|
|
||||||
if newReport:
|
|
||||||
moderationButton = 'buttonhighlighted'
|
|
||||||
if boxName == 'inbox':
|
|
||||||
inboxButton = 'buttonselected'
|
|
||||||
elif boxName == 'tlblogs':
|
|
||||||
blogsButton = 'buttonselected'
|
|
||||||
elif boxName == 'tlfeatures':
|
|
||||||
featuresButton = 'buttonselected'
|
|
||||||
elif boxName == 'tlnews':
|
|
||||||
newsButton = 'buttonselected'
|
|
||||||
elif boxName == 'dm':
|
|
||||||
dmButton = 'buttonselected'
|
|
||||||
if newDM:
|
|
||||||
dmButton = 'buttonselectedhighlighted'
|
|
||||||
elif boxName == 'tlreplies':
|
|
||||||
repliesButton = 'buttonselected'
|
|
||||||
if newReply:
|
|
||||||
repliesButton = 'buttonselectedhighlighted'
|
|
||||||
elif boxName == 'tlmedia':
|
|
||||||
mediaButton = 'buttonselected'
|
|
||||||
elif boxName == 'outbox':
|
|
||||||
sentButton = 'buttonselected'
|
|
||||||
elif boxName == 'moderation':
|
|
||||||
moderationButton = 'buttonselected'
|
|
||||||
if newReport:
|
|
||||||
moderationButton = 'buttonselectedhighlighted'
|
|
||||||
elif boxName == 'tlshares':
|
|
||||||
sharesButton = 'buttonselected'
|
|
||||||
if newShare:
|
|
||||||
sharesButton = 'buttonselectedhighlighted'
|
|
||||||
elif boxName == 'tlbookmarks' or boxName == 'bookmarks':
|
|
||||||
bookmarksButton = 'buttonselected'
|
|
||||||
elif boxName == 'tlevents':
|
|
||||||
eventsButton = 'buttonselected'
|
|
||||||
|
|
||||||
# get the full domain, including any port number
|
# get the full domain, including any port number
|
||||||
fullDomain = getFullDomain(domain, port)
|
fullDomain = getFullDomain(domain, port)
|
||||||
|
|
||||||
|
@ -202,60 +106,12 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
||||||
|
|
||||||
showIndividualPostIcons = True
|
showIndividualPostIcons = True
|
||||||
|
|
||||||
# show an icon for new follow approvals
|
# benchmark 3
|
||||||
followApprovals = ''
|
timeDiff = int((time.time() - timelineStartTime) * 1000)
|
||||||
followRequestsFilename = \
|
if timeDiff > 100:
|
||||||
baseDir + '/accounts/' + \
|
print('TIMELINE TIMING ' + boxName + ' 3 = ' + str(timeDiff))
|
||||||
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 = \
|
|
||||||
'<a href="' + usersPath + \
|
|
||||||
'/followers#buttonheader">' + \
|
|
||||||
'<img loading="lazy" ' + \
|
|
||||||
'class="timelineicon" alt="' + \
|
|
||||||
translate['Approve follow requests'] + \
|
|
||||||
'" title="' + translate['Approve follow requests'] + \
|
|
||||||
'" src="/icons/person.png"/></a>\n'
|
|
||||||
break
|
|
||||||
|
|
||||||
_logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '3')
|
tlStr = htmlHeaderWithExternalStyle(cssFilename, profileStyle)
|
||||||
|
|
||||||
# moderation / reports button
|
|
||||||
moderationButtonStr = ''
|
|
||||||
if moderator and not minimal:
|
|
||||||
moderationButtonStr = \
|
|
||||||
'<a href="' + usersPath + \
|
|
||||||
'/moderation"><button class="' + \
|
|
||||||
moderationButton + '"><span>' + \
|
|
||||||
htmlHighlightLabel(translate['Mod'], newReport) + \
|
|
||||||
' </span></button></a>'
|
|
||||||
|
|
||||||
# shares, bookmarks and events buttons
|
|
||||||
sharesButtonStr = ''
|
|
||||||
bookmarksButtonStr = ''
|
|
||||||
eventsButtonStr = ''
|
|
||||||
if not minimal:
|
|
||||||
sharesButtonStr = \
|
|
||||||
'<a href="' + usersPath + '/tlshares"><button class="' + \
|
|
||||||
sharesButton + '"><span>' + \
|
|
||||||
htmlHighlightLabel(translate['Shares'], newShare) + \
|
|
||||||
'</span></button></a>'
|
|
||||||
|
|
||||||
bookmarksButtonStr = \
|
|
||||||
'<a href="' + usersPath + '/tlbookmarks"><button class="' + \
|
|
||||||
bookmarksButton + '"><span>' + translate['Bookmarks'] + \
|
|
||||||
'</span></button></a>'
|
|
||||||
|
|
||||||
eventsButtonStr = \
|
|
||||||
'<a href="' + usersPath + '/tlevents"><button class="' + \
|
|
||||||
eventsButton + '"><span>' + translate['Events'] + \
|
|
||||||
'</span></button></a>'
|
|
||||||
|
|
||||||
tlStr = htmlHeaderWithExternalStyle(cssFilename)
|
|
||||||
|
|
||||||
_logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '4')
|
_logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '4')
|
||||||
|
|
||||||
|
@ -264,132 +120,28 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
||||||
if defaultTimeline == 'tlfeatures' and boxName == 'tlfeatures':
|
if defaultTimeline == 'tlfeatures' and boxName == 'tlfeatures':
|
||||||
newsHeader = True
|
newsHeader = True
|
||||||
|
|
||||||
newPostButtonStr = ''
|
# Banner and "profile toggle" link
|
||||||
# start of headericons div
|
|
||||||
if not newsHeader:
|
|
||||||
if not iconsAsButtons:
|
|
||||||
newPostButtonStr += '<div class="headericons">'
|
|
||||||
|
|
||||||
# what screen to go to when a new post is created
|
# TODO: This CSS should be moved out of the code
|
||||||
if boxName == 'dm':
|
# Items like this that can be different per user should be kept
|
||||||
if not iconsAsButtons:
|
# in the user's folder and loaded as final CSS, to allow overwrite(s)
|
||||||
newPostButtonStr += \
|
|
||||||
'<a class="imageAnchor" href="' + usersPath + \
|
|
||||||
'/newdm"><img loading="lazy" src="/' + \
|
|
||||||
'icons/newpost.png" title="' + \
|
|
||||||
translate['Create a new DM'] + \
|
|
||||||
'" alt="| ' + translate['Create a new DM'] + \
|
|
||||||
'" class="timelineicon"/></a>\n'
|
|
||||||
else:
|
|
||||||
newPostButtonStr += \
|
|
||||||
'<a href="' + usersPath + '/newdm">' + \
|
|
||||||
'<button class="button"><span>' + \
|
|
||||||
translate['Post'] + ' </span></button></a>'
|
|
||||||
elif (boxName == 'tlblogs' or
|
|
||||||
boxName == 'tlnews' or
|
|
||||||
boxName == 'tlfeatures'):
|
|
||||||
if not iconsAsButtons:
|
|
||||||
newPostButtonStr += \
|
|
||||||
'<a class="imageAnchor" href="' + usersPath + \
|
|
||||||
'/newblog"><img loading="lazy" src="/' + \
|
|
||||||
'icons/newpost.png" title="' + \
|
|
||||||
translate['Create a new post'] + '" alt="| ' + \
|
|
||||||
translate['Create a new post'] + \
|
|
||||||
'" class="timelineicon"/></a>\n'
|
|
||||||
else:
|
|
||||||
newPostButtonStr += \
|
|
||||||
'<a href="' + usersPath + '/newblog">' + \
|
|
||||||
'<button class="button"><span>' + \
|
|
||||||
translate['Post'] + '</span></button></a>'
|
|
||||||
elif boxName == 'tlevents':
|
|
||||||
if not iconsAsButtons:
|
|
||||||
newPostButtonStr += \
|
|
||||||
'<a class="imageAnchor" href="' + usersPath + \
|
|
||||||
'/newevent"><img loading="lazy" src="/' + \
|
|
||||||
'icons/newpost.png" title="' + \
|
|
||||||
translate['Create a new event'] + '" alt="| ' + \
|
|
||||||
translate['Create a new event'] + \
|
|
||||||
'" class="timelineicon"/></a>\n'
|
|
||||||
else:
|
|
||||||
newPostButtonStr += \
|
|
||||||
'<a href="' + usersPath + '/newevent">' + \
|
|
||||||
'<button class="button"><span>' + \
|
|
||||||
translate['Post'] + '</span></button></a>'
|
|
||||||
elif boxName == 'tlshares':
|
|
||||||
if not iconsAsButtons:
|
|
||||||
newPostButtonStr += \
|
|
||||||
'<a class="imageAnchor" href="' + usersPath + \
|
|
||||||
'/newshare"><img loading="lazy" src="/' + \
|
|
||||||
'icons/newpost.png" title="' + \
|
|
||||||
translate['Create a new shared item'] + '" alt="| ' + \
|
|
||||||
translate['Create a new shared item'] + \
|
|
||||||
'" class="timelineicon"/></a>\n'
|
|
||||||
else:
|
|
||||||
newPostButtonStr += \
|
|
||||||
'<a href="' + usersPath + '/newshare">' + \
|
|
||||||
'<button class="button"><span>' + \
|
|
||||||
translate['Post'] + '</span></button></a>'
|
|
||||||
else:
|
|
||||||
if not manuallyApproveFollowers:
|
|
||||||
if not iconsAsButtons:
|
|
||||||
newPostButtonStr += \
|
|
||||||
'<a class="imageAnchor" href="' + usersPath + \
|
|
||||||
'/newpost"><img loading="lazy" src="/' + \
|
|
||||||
'icons/newpost.png" title="' + \
|
|
||||||
translate['Create a new post'] + '" alt="| ' + \
|
|
||||||
translate['Create a new post'] + \
|
|
||||||
'" class="timelineicon"/></a>\n'
|
|
||||||
else:
|
|
||||||
newPostButtonStr += \
|
|
||||||
'<a href="' + usersPath + '/newpost">' + \
|
|
||||||
'<button class="button"><span>' + \
|
|
||||||
translate['Post'] + '</span></button></a>'
|
|
||||||
else:
|
|
||||||
if not iconsAsButtons:
|
|
||||||
newPostButtonStr += \
|
|
||||||
'<a class="imageAnchor" href="' + usersPath + \
|
|
||||||
'/newfollowers"><img loading="lazy" src="/' + \
|
|
||||||
'icons/newpost.png" title="' + \
|
|
||||||
translate['Create a new post'] + \
|
|
||||||
'" alt="| ' + translate['Create a new post'] + \
|
|
||||||
'" class="timelineicon"/></a>\n'
|
|
||||||
else:
|
|
||||||
newPostButtonStr += \
|
|
||||||
'<a href="' + usersPath + '/newfollowers">' + \
|
|
||||||
'<button class="button"><span>' + \
|
|
||||||
translate['Post'] + '</span></button></a>'
|
|
||||||
|
|
||||||
# This creates a link to the profile page when viewed
|
|
||||||
# in lynx, but should be invisible in a graphical web browser
|
|
||||||
tlStr += \
|
tlStr += \
|
||||||
'<div class="transparent"><label class="transparent">' + \
|
'<a class="timeline-banner hidden-text" href="/users/' + nickname + '" title="' + \
|
||||||
'<a href="/users/' + nickname + '">' + \
|
|
||||||
translate['Switch to profile view'] + '</a></label></div>\n'
|
|
||||||
|
|
||||||
# banner and row of buttons
|
|
||||||
tlStr += \
|
|
||||||
'<header>\n' + \
|
|
||||||
'<a href="/users/' + nickname + '" title="' + \
|
|
||||||
translate['Switch to profile view'] + '" alt="' + \
|
translate['Switch to profile view'] + '" alt="' + \
|
||||||
translate['Switch to profile view'] + '">\n'
|
translate['Switch to profile view'] + '" style="' + \
|
||||||
tlStr += '<img loading="lazy" class="timeline-banner" src="' + \
|
'background-image: url(\'' + usersPath + '/' + bannerFile + '\');">' + \
|
||||||
usersPath + '/' + bannerFile + '" /></a>\n' + \
|
translate['Switch to profile view'] + '</a>\n'
|
||||||
'</header>\n'
|
|
||||||
|
|
||||||
if fullWidthTimelineButtonHeader:
|
|
||||||
|
# Full Row of Buttons
|
||||||
tlStr += \
|
tlStr += \
|
||||||
headerButtonsTimeline(defaultTimeline, boxName, pageNumber,
|
headerButtonsTimeline(defaultTimeline, boxName, pageNumber,
|
||||||
translate, usersPath, mediaButton,
|
translate, usersPath,
|
||||||
blogsButton, featuresButton,
|
minimal, moderator,
|
||||||
newsButton, inboxButton,
|
manuallyApproveFollowers,
|
||||||
dmButton, newDM, repliesButton,
|
baseDir, nickname,
|
||||||
newReply, minimal, sentButton,
|
domain, iconsDir, timelineStartTime,
|
||||||
sharesButtonStr, bookmarksButtonStr,
|
|
||||||
eventsButtonStr, moderationButtonStr,
|
|
||||||
newPostButtonStr, baseDir, nickname,
|
|
||||||
domain, timelineStartTime,
|
|
||||||
newCalendarEvent, calendarPath,
|
|
||||||
calendarImage, followApprovals,
|
|
||||||
iconsAsButtons)
|
iconsAsButtons)
|
||||||
|
|
||||||
# start the timeline
|
# start the timeline
|
||||||
|
@ -408,24 +160,6 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
||||||
# center column containing posts
|
# center column containing posts
|
||||||
tlStr += ' <div class="col-center">\n'
|
tlStr += ' <div class="col-center">\n'
|
||||||
|
|
||||||
if not fullWidthTimelineButtonHeader:
|
|
||||||
tlStr += \
|
|
||||||
headerButtonsTimeline(defaultTimeline, boxName, pageNumber,
|
|
||||||
translate, usersPath, mediaButton,
|
|
||||||
blogsButton, featuresButton,
|
|
||||||
newsButton, inboxButton,
|
|
||||||
dmButton, newDM, repliesButton,
|
|
||||||
newReply, minimal, sentButton,
|
|
||||||
sharesButtonStr, bookmarksButtonStr,
|
|
||||||
eventsButtonStr, moderationButtonStr,
|
|
||||||
newPostButtonStr, baseDir, nickname,
|
|
||||||
domain, timelineStartTime,
|
|
||||||
newCalendarEvent, calendarPath,
|
|
||||||
calendarImage, followApprovals,
|
|
||||||
iconsAsButtons)
|
|
||||||
|
|
||||||
tlStr += ' <div class="timeline-posts">\n'
|
|
||||||
|
|
||||||
# second row of buttons for moderator actions
|
# second row of buttons for moderator actions
|
||||||
if moderator and boxName == 'moderation':
|
if moderator and boxName == 'moderation':
|
||||||
tlStr += \
|
tlStr += \
|
||||||
|
@ -701,6 +435,449 @@ def _htmlSharesTimeline(translate: {}, pageNumber: int, itemsPerPage: int,
|
||||||
return timelineStr
|
return timelineStr
|
||||||
|
|
||||||
|
|
||||||
|
# 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,
|
||||||
|
iconsDir: str,
|
||||||
|
timelineStartTime,
|
||||||
|
iconsAsButtons: bool) -> str:
|
||||||
|
"""Returns the header at the top of the timeline, containing
|
||||||
|
buttons for inbox, outbox, search, calendar, etc
|
||||||
|
"""
|
||||||
|
# TODO: Create menu buttons via loop(s)
|
||||||
|
|
||||||
|
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 = '<div class="containerHeader">\n'
|
||||||
|
|
||||||
|
# if this is a news instance and we are viewing the news timeline
|
||||||
|
newsHeader = False
|
||||||
|
if defaultTimeline == 'tlnews' and boxName == 'tlnews':
|
||||||
|
newsHeader = True
|
||||||
|
|
||||||
|
# if not newsHeader:
|
||||||
|
# tlStr += \
|
||||||
|
# '<a href="' + usersPath + \
|
||||||
|
# '/dm"><button class="' + dmButton + \
|
||||||
|
# '"><span>' + htmlHighlightLabel(translate['DM'], newDM) + \
|
||||||
|
# '</span></button></a>'
|
||||||
|
#
|
||||||
|
# tlStr += \
|
||||||
|
# '<a href="' + usersPath + '/tlreplies"><button class="' + \
|
||||||
|
# repliesButton + '"><span>' + \
|
||||||
|
# htmlHighlightLabel(translate['Replies'], newReply) + \
|
||||||
|
# '</span></button></a>'
|
||||||
|
|
||||||
|
isFeaturesTimeline = \
|
||||||
|
defaultTimeline == 'tlnews' and boxName == 'tlnews'
|
||||||
|
|
||||||
|
# TODO: Convert to new approach - append to 'actionButtonList'
|
||||||
|
# show todays events buttons on the first inbox page
|
||||||
|
happeningStr = ''
|
||||||
|
if boxName == 'inbox' and pageNumber == 1:
|
||||||
|
if todaysEventsCheck(baseDir, nickname, domain):
|
||||||
|
now = datetime.now()
|
||||||
|
|
||||||
|
# happening today button
|
||||||
|
if not iconsAsButtons:
|
||||||
|
happeningStr += \
|
||||||
|
'<a href="' + usersPath + '/calendar?year=' + \
|
||||||
|
str(now.year) + '?month=' + str(now.month) + \
|
||||||
|
'?day=' + str(now.day) + '">' + \
|
||||||
|
'<button class="buttonevent">' + \
|
||||||
|
translate['Happening Today'] + '</button></a>'
|
||||||
|
else:
|
||||||
|
happeningStr += \
|
||||||
|
'<a href="' + usersPath + '/calendar?year=' + \
|
||||||
|
str(now.year) + '?month=' + str(now.month) + \
|
||||||
|
'?day=' + str(now.day) + '">' + \
|
||||||
|
'<button class="button">' + \
|
||||||
|
translate['Happening Today'] + '</button></a>'
|
||||||
|
|
||||||
|
# happening this week button
|
||||||
|
if thisWeeksEventsCheck(baseDir, nickname, domain):
|
||||||
|
if not iconsAsButtons:
|
||||||
|
happeningStr += \
|
||||||
|
'<a href="' + usersPath + \
|
||||||
|
'/calendar"><button class="buttonevent">' + \
|
||||||
|
translate['Happening This Week'] + '</button></a>'
|
||||||
|
else:
|
||||||
|
happeningStr += \
|
||||||
|
'<a href="' + usersPath + \
|
||||||
|
'/calendar"><button class="button">' + \
|
||||||
|
translate['Happening This Week'] + '</button></a>'
|
||||||
|
else:
|
||||||
|
# happening this week button
|
||||||
|
if thisWeeksEventsCheck(baseDir, nickname, domain):
|
||||||
|
if not iconsAsButtons:
|
||||||
|
happeningStr += \
|
||||||
|
'<a href="' + usersPath + \
|
||||||
|
'/calendar"><button class="buttonevent">' + \
|
||||||
|
translate['Happening This Week'] + '</button></a>'
|
||||||
|
else:
|
||||||
|
happeningStr += \
|
||||||
|
'<a href="' + usersPath + \
|
||||||
|
'/calendar"><button class="button">' + \
|
||||||
|
translate['Happening This Week'] + '</button></a>'
|
||||||
|
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# 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-styled
|
||||||
|
|
||||||
|
# A list of buttons to be rendered as html,
|
||||||
|
# each item being a dictionary containing its unique info.
|
||||||
|
# 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 really be even for non-news instances ?
|
||||||
|
|
||||||
|
# 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 = '<div class="navbuttons">\n'
|
||||||
|
navButtonStr += '<ul class="menu">\n'
|
||||||
|
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 += '<a class="' + classStr + '"' + \
|
||||||
|
'href="' + usersPath + config['pageRef'] + '">\n' + \
|
||||||
|
'<li>' + textStr
|
||||||
|
navButtonStr += '</li>\n' + \
|
||||||
|
'</a>\n'
|
||||||
|
navButtonStr += '</ul>\n</div>\n'
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
if followApprovals:
|
||||||
|
actionButtonList.append(('followers',
|
||||||
|
{'pageRef': '/followers',
|
||||||
|
'translateText': 'Approve follow requests',
|
||||||
|
'iconClass': 'icon-newfollow'}
|
||||||
|
))
|
||||||
|
|
||||||
|
# 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(('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'}
|
||||||
|
))
|
||||||
|
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 = '<div class="actionbuttons">\n'
|
||||||
|
actionButtonStr += '<ul class="menu">\n'
|
||||||
|
|
||||||
|
# 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']
|
||||||
|
|
||||||
|
actionButtonStr += '<a class="' + classStr + '"' + \
|
||||||
|
'href="' + usersPath + config['pageRef'] + '">\n' + \
|
||||||
|
'<li>'
|
||||||
|
if 'highlightLabel' in config:
|
||||||
|
actionButtonStr += htmlHighlightLabel(translate[config['translateText']], \
|
||||||
|
config['highlightLabel'])
|
||||||
|
else:
|
||||||
|
actionButtonStr += translate[config['translateText']]
|
||||||
|
actionButtonStr += '</li>\n' + \
|
||||||
|
'</a>\n'
|
||||||
|
|
||||||
|
actionButtonStr += '</ul>\n</div>\n'
|
||||||
|
|
||||||
|
|
||||||
|
# benchmark 5
|
||||||
|
timeDiff = int((time.time() - timelineStartTime) * 1000)
|
||||||
|
if timeDiff > 100:
|
||||||
|
print('TIMELINE TIMING ' + boxName + ' 5 = ' + str(timeDiff))
|
||||||
|
|
||||||
|
# if not newsHeader:
|
||||||
|
# # the show/hide button, for a simpler header appearance
|
||||||
|
# if not iconsAsButtons:
|
||||||
|
# tlStr += \
|
||||||
|
# ' <a class="imageAnchor" href="' + \
|
||||||
|
# usersPath + '/minimal' + \
|
||||||
|
# '"><img loading="lazy" src="/' + iconsDir + \
|
||||||
|
# '/showhide.png" title="' + translate['Show/Hide Buttons'] + \
|
||||||
|
# '" alt="| ' + translate['Show/Hide Buttons'] + \
|
||||||
|
# '" class="timelineicon"/></a>\n'
|
||||||
|
# else:
|
||||||
|
# tlStr += \
|
||||||
|
# '<a href="' + usersPath + '/minimal' + \
|
||||||
|
# '"><button class="button">' + \
|
||||||
|
# '<span>' + translate['Expand'] + \
|
||||||
|
# '</span></button></a>'
|
||||||
|
# else:
|
||||||
|
# tlStr += \
|
||||||
|
# '<a href="' + usersPath + '/inbox">' + \
|
||||||
|
# '<button class="button">' + \
|
||||||
|
# '<span>' + translate['User'] + '</span></button></a>'
|
||||||
|
# tlStr += \
|
||||||
|
# '<a href="' + usersPath + '/editprofile">' + \
|
||||||
|
# '<button class="buttonDesktop">' + \
|
||||||
|
# '<span>' + translate['Settings'] + '</span></button></a>'
|
||||||
|
|
||||||
|
# Compile HTML parts
|
||||||
|
tlStr += navButtonStr + actionButtonStr + happeningStr
|
||||||
|
|
||||||
|
# TODO: Integrate this logic in new approach - if ultimately necessary
|
||||||
|
# if not newsHeader:
|
||||||
|
# tlStr += followApprovals
|
||||||
|
|
||||||
|
# end of the button header with inbox, outbox, etc
|
||||||
|
tlStr += ' </div>\n'
|
||||||
|
return tlStr
|
||||||
|
|
||||||
|
|
||||||
def htmlShares(cssCache: {}, defaultTimeline: str,
|
def htmlShares(cssCache: {}, defaultTimeline: str,
|
||||||
recentPostsCache: {}, maxRecentPosts: int,
|
recentPostsCache: {}, maxRecentPosts: int,
|
||||||
translate: {}, pageNumber: int, itemsPerPage: int,
|
translate: {}, pageNumber: int, itemsPerPage: int,
|
||||||
|
|
Loading…
Reference in New Issue