diff --git a/webapp_timeline.py b/webapp_timeline.py index 80f2f17d..9e65b3d6 100644 --- a/webapp_timeline.py +++ b/webapp_timeline.py @@ -18,7 +18,7 @@ from happening import thisWeeksEventsCheck from webapp_utils import getIconsDir from webapp_utils import htmlPostSeparator from webapp_utils import getBannerFile -from webapp_utils import htmlHeader +from webapp_utils import htmlHeaderWithExternalStyle from webapp_utils import htmlFooter from webapp_utils import sharesTimelineJson from webapp_post import preparePostFromHtmlCache @@ -29,6 +29,600 @@ from posts import isModerator from posts import isEditor +def htmlTimeline(cssCache: {}, defaultTimeline: str, + recentPostsCache: {}, maxRecentPosts: int, + translate: {}, pageNumber: int, + itemsPerPage: int, session, baseDir: str, + wfRequest: {}, personCache: {}, + 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, + authorized: bool) -> str: + """Show the timeline as html + """ + timelineStartTime = time.time() + + 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) + + # directory where icons are found + # This changes depending upon theme + iconsDir = getIconsDir(baseDir) + + separatorStr = '' + if boxName != 'tlmedia': + separatorStr = htmlPostSeparator(baseDir, None) + + # the css filename + cssFilename = baseDir + '/epicyon-profile.css' + if os.path.isfile(baseDir + '/epicyon.css'): + cssFilename = baseDir + '/epicyon.css' + + # filename of the banner shown at the top + bannerFile, bannerFilename = getBannerFile(baseDir, nickname, domain) + + # benchmark 1 + timeDiff = int((time.time() - timelineStartTime) * 1000) + if timeDiff > 100: + print('TIMELINE TIMING ' + boxName + ' 1 = ' + str(timeDiff)) + + profileStyle = getCSS(baseDir, cssFilename, cssCache) + if not profileStyle: + print('ERROR: css file not found ' + cssFilename) + return None + + # replace any https within the css with whatever prefix is needed + if httpPrefix != 'https': + profileStyle = \ + profileStyle.replace('https://', + httpPrefix + '://') + + # is the user a moderator? + if not moderator: + moderator = isModerator(baseDir, nickname) + + # is the user a site editor? + if not editor: + editor = isEditor(baseDir, nickname) + + # benchmark 2 + timeDiff = int((time.time() - timelineStartTime) * 1000) + if timeDiff > 100: + print('TIMELINE TIMING ' + boxName + ' 2 = ' + str(timeDiff)) + + # the appearance of buttons - highlighted or not + inboxButton = 'button' + blogsButton = '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 == '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 + fullDomain = domain + if port != 80 and port != 443: + if ':' not in domain: + fullDomain = domain + ':' + str(port) + + usersPath = '/users/' + nickname + actor = httpPrefix + '://' + fullDomain + usersPath + + showIndividualPostIcons = True + + # show an icon for new follow approvals + followApprovals = '' + 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 = \ + '' + \ + '' + \
+                        translate['Approve follow requests'] + \
+                        '\n' + break + + # benchmark 3 + timeDiff = int((time.time() - timelineStartTime) * 1000) + if timeDiff > 100: + print('TIMELINE TIMING ' + boxName + ' 3 = ' + str(timeDiff)) + + # moderation / reports button + moderationButtonStr = '' + if moderator and not minimal: + moderationButtonStr = \ + '' + + # shares, bookmarks and events buttons + sharesButtonStr = '' + bookmarksButtonStr = '' + eventsButtonStr = '' + if not minimal: + sharesButtonStr = \ + '' + + bookmarksButtonStr = \ + '' + + eventsButtonStr = \ + '' + + tlStr = htmlHeaderWithExternalStyle(cssFilename, profileStyle) + + # benchmark 4 + timeDiff = int((time.time() - timelineStartTime) * 1000) + if timeDiff > 100: + print('TIMELINE TIMING ' + boxName + ' 4 = ' + str(timeDiff)) + + # if this is a news instance and we are viewing the news timeline + newsHeader = False + if defaultTimeline == 'tlnews' and boxName == 'tlnews': + newsHeader = True + + newPostButtonStr = '' + # start of headericons div + if not newsHeader: + if not iconsAsButtons: + newPostButtonStr += '
' + + # what screen to go to when a new post is created + if boxName == 'dm': + if not iconsAsButtons: + newPostButtonStr += \ + '| ' + translate['Create a new DM'] + \
+                '\n' + else: + newPostButtonStr += \ + '' + \ + '' + elif boxName == 'tlblogs' or boxName == 'tlnews': + if not iconsAsButtons: + newPostButtonStr += \ + '| ' + \
+                translate['Create a new post'] + \
+                '\n' + else: + newPostButtonStr += \ + '' + \ + '' + elif boxName == 'tlevents': + if not iconsAsButtons: + newPostButtonStr += \ + '| ' + \
+                translate['Create a new event'] + \
+                '\n' + else: + newPostButtonStr += \ + '' + \ + '' + else: + if not manuallyApproveFollowers: + if not iconsAsButtons: + newPostButtonStr += \ + '| ' + \
+                    translate['Create a new post'] + \
+                    '\n' + else: + newPostButtonStr += \ + '' + \ + '' + else: + if not iconsAsButtons: + newPostButtonStr += \ + '| ' + translate['Create a new post'] + \
+                    '\n' + else: + newPostButtonStr += \ + '' + \ + '' + + # This creates a link to the profile page when viewed + # in lynx, but should be invisible in a graphical web browser + tlStr += \ + '
\n' + + # banner and row of buttons + tlStr += \ + '\n' + tlStr += '\n' + + if fullWidthTimelineButtonHeader: + tlStr += \ + headerButtonsTimeline(defaultTimeline, boxName, pageNumber, + translate, usersPath, mediaButton, + blogsButton, newsButton, inboxButton, + dmButton, newDM, repliesButton, + newReply, minimal, sentButton, + sharesButtonStr, bookmarksButtonStr, + eventsButtonStr, moderationButtonStr, + newPostButtonStr, baseDir, nickname, + domain, iconsDir, timelineStartTime, + newCalendarEvent, calendarPath, + calendarImage, followApprovals, + iconsAsButtons) + + # start the timeline + tlStr += '\n' + tlStr += ' \n' + tlStr += ' \n' + tlStr += ' \n' + tlStr += ' \n' + tlStr += ' \n' + tlStr += ' \n' + tlStr += ' \n' + + domainFull = domain + if port: + if port != 80 and port != 443: + domainFull = domain + ':' + str(port) + + # left column + leftColumnStr = \ + getLeftColumnContent(baseDir, nickname, domainFull, + httpPrefix, translate, iconsDir, + editor, False, None, rssIconAtTop, + True, False) + tlStr += ' \n' + # center column containing posts + tlStr += ' \n' + + # right column + rightColumnStr = getRightColumnContent(baseDir, nickname, domainFull, + httpPrefix, translate, iconsDir, + moderator, editor, + newswire, positiveVoting, + False, None, True, + showPublishAsIcon, + rssIconAtTop, publishButtonAtTop, + authorized, True) + tlStr += ' \n' + tlStr += ' \n' + + # benchmark 9 + timeDiff = int((time.time() - timelineStartTime) * 1000) + if timeDiff > 100: + print('TIMELINE TIMING ' + boxName + ' 9 = ' + str(timeDiff)) + + tlStr += ' \n' + tlStr += '
' + \ + leftColumnStr + ' \n' + + if not fullWidthTimelineButtonHeader: + tlStr += \ + headerButtonsTimeline(defaultTimeline, boxName, pageNumber, + translate, usersPath, mediaButton, + blogsButton, newsButton, inboxButton, + dmButton, newDM, repliesButton, + newReply, minimal, sentButton, + sharesButtonStr, bookmarksButtonStr, + eventsButtonStr, moderationButtonStr, + newPostButtonStr, baseDir, nickname, + domain, iconsDir, timelineStartTime, + newCalendarEvent, calendarPath, + calendarImage, followApprovals, + iconsAsButtons) + + # 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' + tlStr += \ + ' ' + translate[idx] + '
\n' + tlStr += '
\n' + tlStr += \ + ' \n' + tlStr += \ + ' \n' + tlStr += \ + ' \n' + tlStr += \ + ' \n' + tlStr += \ + ' \n' + tlStr += \ + ' \n' + tlStr += '
\n
\n' + + # benchmark 6 + timeDiff = int((time.time() - timelineStartTime) * 1000) + if timeDiff > 100: + print('TIMELINE TIMING ' + boxName + ' 6 = ' + str(timeDiff)) + + if boxName == 'tlshares': + maxSharesPerAccount = itemsPerPage + return (tlStr + + htmlSharesTimeline(translate, pageNumber, itemsPerPage, + baseDir, actor, nickname, domain, port, + maxSharesPerAccount, httpPrefix) + + htmlFooter()) + + # benchmark 7 + timeDiff = int((time.time() - timelineStartTime) * 1000) + if timeDiff > 100: + print('TIMELINE TIMING ' + boxName + ' 7 = ' + str(timeDiff)) + + # benchmark 8 + timeDiff = int((time.time() - timelineStartTime) * 1000) + if timeDiff > 100: + print('TIMELINE TIMING ' + boxName + ' 8 = ' + str(timeDiff)) + + # page up arrow + if pageNumber > 1: + tlStr += \ + '
\n' + \ + ' ' + \
+            translate['Page up'] + '\n' + \ + '
\n' + + # 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 += '
' + tlStr += '
\n' + + # show each post in the timeline + for item in timelineJson['orderedItems']: + timelinePostStartTime = time.time() + + 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 + + # 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) + # benchmark cache post + timeDiff = \ + int((time.time() - + timelinePostStartTime) * 1000) + if timeDiff > 100: + print('TIMELINE POST CACHE TIMING ' + + boxName + ' = ' + str(timeDiff)) + + if not currTlStr: + # benchmark cache post + timeDiff = \ + int((time.time() - + timelinePostStartTime) * 1000) + if timeDiff > 100: + print('TIMELINE POST DISK TIMING START ' + + boxName + ' = ' + str(timeDiff)) + + # read the post from disk + currTlStr = \ + individualPostAsHtml(False, recentPostsCache, + maxRecentPosts, + iconsDir, translate, pageNumber, + baseDir, session, wfRequest, + personCache, + nickname, domain, port, + item, None, True, + allowDeletion, + httpPrefix, projectVersion, + boxName, + YTReplacementDomain, + showPublishedDateOnly, + boxName != 'dm', + showIndividualPostIcons, + manuallyApproveFollowers, + False, True) + # benchmark cache post + timeDiff = \ + int((time.time() - + timelinePostStartTime) * 1000) + if timeDiff > 100: + print('TIMELINE POST DISK TIMING ' + + boxName + ' = ' + str(timeDiff)) + + if currTlStr: + itemCtr += 1 + if separatorStr: + tlStr += separatorStr + tlStr += currTlStr + if boxName == 'tlmedia': + tlStr += '
\n' + + # page down arrow + if itemCtr > 2: + tlStr += \ + '
\n' + \ + ' ' + \
+            translate['Page down'] + '\n' + \ + '
\n' + + # end of column-center + tlStr += '
' + \ + rightColumnStr + '
\n' + tlStr += htmlFooter() + return tlStr + + def htmlIndividualShare(actor: str, item: {}, translate: {}, showContact: bool, removeButton: bool) -> str: """Returns an individual shared item as html @@ -440,600 +1034,6 @@ def headerButtonsTimeline(defaultTimeline: str, return tlStr -def htmlTimeline(cssCache: {}, defaultTimeline: str, - recentPostsCache: {}, maxRecentPosts: int, - translate: {}, pageNumber: int, - itemsPerPage: int, session, baseDir: str, - wfRequest: {}, personCache: {}, - 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, - authorized: bool) -> str: - """Show the timeline as html - """ - timelineStartTime = time.time() - - 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) - - # directory where icons are found - # This changes depending upon theme - iconsDir = getIconsDir(baseDir) - - separatorStr = '' - if boxName != 'tlmedia': - separatorStr = htmlPostSeparator(baseDir, None) - - # the css filename - cssFilename = baseDir + '/epicyon-profile.css' - if os.path.isfile(baseDir + '/epicyon.css'): - cssFilename = baseDir + '/epicyon.css' - - # filename of the banner shown at the top - bannerFile, bannerFilename = getBannerFile(baseDir, nickname, domain) - - # benchmark 1 - timeDiff = int((time.time() - timelineStartTime) * 1000) - if timeDiff > 100: - print('TIMELINE TIMING ' + boxName + ' 1 = ' + str(timeDiff)) - - profileStyle = getCSS(baseDir, cssFilename, cssCache) - if not profileStyle: - print('ERROR: css file not found ' + cssFilename) - return None - - # replace any https within the css with whatever prefix is needed - if httpPrefix != 'https': - profileStyle = \ - profileStyle.replace('https://', - httpPrefix + '://') - - # is the user a moderator? - if not moderator: - moderator = isModerator(baseDir, nickname) - - # is the user a site editor? - if not editor: - editor = isEditor(baseDir, nickname) - - # benchmark 2 - timeDiff = int((time.time() - timelineStartTime) * 1000) - if timeDiff > 100: - print('TIMELINE TIMING ' + boxName + ' 2 = ' + str(timeDiff)) - - # the appearance of buttons - highlighted or not - inboxButton = 'button' - blogsButton = '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 == '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 - fullDomain = domain - if port != 80 and port != 443: - if ':' not in domain: - fullDomain = domain + ':' + str(port) - - usersPath = '/users/' + nickname - actor = httpPrefix + '://' + fullDomain + usersPath - - showIndividualPostIcons = True - - # show an icon for new follow approvals - followApprovals = '' - 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 = \ - '' + \ - '' + \
-                        translate['Approve follow requests'] + \
-                        '\n' - break - - # benchmark 3 - timeDiff = int((time.time() - timelineStartTime) * 1000) - if timeDiff > 100: - print('TIMELINE TIMING ' + boxName + ' 3 = ' + str(timeDiff)) - - # moderation / reports button - moderationButtonStr = '' - if moderator and not minimal: - moderationButtonStr = \ - '' - - # shares, bookmarks and events buttons - sharesButtonStr = '' - bookmarksButtonStr = '' - eventsButtonStr = '' - if not minimal: - sharesButtonStr = \ - '' - - bookmarksButtonStr = \ - '' - - eventsButtonStr = \ - '' - - tlStr = htmlHeader(cssFilename, profileStyle) - - # benchmark 4 - timeDiff = int((time.time() - timelineStartTime) * 1000) - if timeDiff > 100: - print('TIMELINE TIMING ' + boxName + ' 4 = ' + str(timeDiff)) - - # if this is a news instance and we are viewing the news timeline - newsHeader = False - if defaultTimeline == 'tlnews' and boxName == 'tlnews': - newsHeader = True - - newPostButtonStr = '' - # start of headericons div - if not newsHeader: - if not iconsAsButtons: - newPostButtonStr += '
' - - # what screen to go to when a new post is created - if boxName == 'dm': - if not iconsAsButtons: - newPostButtonStr += \ - '| ' + translate['Create a new DM'] + \
-                '\n' - else: - newPostButtonStr += \ - '' + \ - '' - elif boxName == 'tlblogs' or boxName == 'tlnews': - if not iconsAsButtons: - newPostButtonStr += \ - '| ' + \
-                translate['Create a new post'] + \
-                '\n' - else: - newPostButtonStr += \ - '' + \ - '' - elif boxName == 'tlevents': - if not iconsAsButtons: - newPostButtonStr += \ - '| ' + \
-                translate['Create a new event'] + \
-                '\n' - else: - newPostButtonStr += \ - '' + \ - '' - else: - if not manuallyApproveFollowers: - if not iconsAsButtons: - newPostButtonStr += \ - '| ' + \
-                    translate['Create a new post'] + \
-                    '\n' - else: - newPostButtonStr += \ - '' + \ - '' - else: - if not iconsAsButtons: - newPostButtonStr += \ - '| ' + translate['Create a new post'] + \
-                    '\n' - else: - newPostButtonStr += \ - '' + \ - '' - - # This creates a link to the profile page when viewed - # in lynx, but should be invisible in a graphical web browser - tlStr += \ - '\n' - - # banner and row of buttons - tlStr += \ - '\n' - tlStr += '\n' - - if fullWidthTimelineButtonHeader: - tlStr += \ - headerButtonsTimeline(defaultTimeline, boxName, pageNumber, - translate, usersPath, mediaButton, - blogsButton, newsButton, inboxButton, - dmButton, newDM, repliesButton, - newReply, minimal, sentButton, - sharesButtonStr, bookmarksButtonStr, - eventsButtonStr, moderationButtonStr, - newPostButtonStr, baseDir, nickname, - domain, iconsDir, timelineStartTime, - newCalendarEvent, calendarPath, - calendarImage, followApprovals, - iconsAsButtons) - - # start the timeline - tlStr += '\n' - tlStr += ' \n' - tlStr += ' \n' - tlStr += ' \n' - tlStr += ' \n' - tlStr += ' \n' - tlStr += ' \n' - tlStr += ' \n' - - domainFull = domain - if port: - if port != 80 and port != 443: - domainFull = domain + ':' + str(port) - - # left column - leftColumnStr = \ - getLeftColumnContent(baseDir, nickname, domainFull, - httpPrefix, translate, iconsDir, - editor, False, None, rssIconAtTop, - True, False) - tlStr += ' \n' - # center column containing posts - tlStr += ' \n' - - # right column - rightColumnStr = getRightColumnContent(baseDir, nickname, domainFull, - httpPrefix, translate, iconsDir, - moderator, editor, - newswire, positiveVoting, - False, None, True, - showPublishAsIcon, - rssIconAtTop, publishButtonAtTop, - authorized, True) - tlStr += ' \n' - tlStr += ' \n' - - # benchmark 9 - timeDiff = int((time.time() - timelineStartTime) * 1000) - if timeDiff > 100: - print('TIMELINE TIMING ' + boxName + ' 9 = ' + str(timeDiff)) - - tlStr += ' \n' - tlStr += '
' + \ - leftColumnStr + ' \n' - - if not fullWidthTimelineButtonHeader: - tlStr += \ - headerButtonsTimeline(defaultTimeline, boxName, pageNumber, - translate, usersPath, mediaButton, - blogsButton, newsButton, inboxButton, - dmButton, newDM, repliesButton, - newReply, minimal, sentButton, - sharesButtonStr, bookmarksButtonStr, - eventsButtonStr, moderationButtonStr, - newPostButtonStr, baseDir, nickname, - domain, iconsDir, timelineStartTime, - newCalendarEvent, calendarPath, - calendarImage, followApprovals, - iconsAsButtons) - - # 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' - tlStr += \ - ' ' + translate[idx] + '
\n' - tlStr += '
\n' - tlStr += \ - ' \n' - tlStr += \ - ' \n' - tlStr += \ - ' \n' - tlStr += \ - ' \n' - tlStr += \ - ' \n' - tlStr += \ - ' \n' - tlStr += '
\n
\n' - - # benchmark 6 - timeDiff = int((time.time() - timelineStartTime) * 1000) - if timeDiff > 100: - print('TIMELINE TIMING ' + boxName + ' 6 = ' + str(timeDiff)) - - if boxName == 'tlshares': - maxSharesPerAccount = itemsPerPage - return (tlStr + - htmlSharesTimeline(translate, pageNumber, itemsPerPage, - baseDir, actor, nickname, domain, port, - maxSharesPerAccount, httpPrefix) + - htmlFooter()) - - # benchmark 7 - timeDiff = int((time.time() - timelineStartTime) * 1000) - if timeDiff > 100: - print('TIMELINE TIMING ' + boxName + ' 7 = ' + str(timeDiff)) - - # benchmark 8 - timeDiff = int((time.time() - timelineStartTime) * 1000) - if timeDiff > 100: - print('TIMELINE TIMING ' + boxName + ' 8 = ' + str(timeDiff)) - - # page up arrow - if pageNumber > 1: - tlStr += \ - '
\n' + \ - ' ' + \
-            translate['Page up'] + '\n' + \ - '
\n' - - # 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 += '
' - tlStr += '
\n' - - # show each post in the timeline - for item in timelineJson['orderedItems']: - timelinePostStartTime = time.time() - - 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 - - # 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) - # benchmark cache post - timeDiff = \ - int((time.time() - - timelinePostStartTime) * 1000) - if timeDiff > 100: - print('TIMELINE POST CACHE TIMING ' + - boxName + ' = ' + str(timeDiff)) - - if not currTlStr: - # benchmark cache post - timeDiff = \ - int((time.time() - - timelinePostStartTime) * 1000) - if timeDiff > 100: - print('TIMELINE POST DISK TIMING START ' + - boxName + ' = ' + str(timeDiff)) - - # read the post from disk - currTlStr = \ - individualPostAsHtml(False, recentPostsCache, - maxRecentPosts, - iconsDir, translate, pageNumber, - baseDir, session, wfRequest, - personCache, - nickname, domain, port, - item, None, True, - allowDeletion, - httpPrefix, projectVersion, - boxName, - YTReplacementDomain, - showPublishedDateOnly, - boxName != 'dm', - showIndividualPostIcons, - manuallyApproveFollowers, - False, True) - # benchmark cache post - timeDiff = \ - int((time.time() - - timelinePostStartTime) * 1000) - if timeDiff > 100: - print('TIMELINE POST DISK TIMING ' + - boxName + ' = ' + str(timeDiff)) - - if currTlStr: - itemCtr += 1 - if separatorStr: - tlStr += separatorStr - tlStr += currTlStr - if boxName == 'tlmedia': - tlStr += '
\n' - - # page down arrow - if itemCtr > 2: - tlStr += \ - '
\n' + \ - ' ' + \
-            translate['Page down'] + '\n' + \ - '
\n' - - # end of column-center - tlStr += '
' + \ - rightColumnStr + '
\n' - tlStr += htmlFooter() - return tlStr - - def htmlShares(cssCache: {}, defaultTimeline: str, recentPostsCache: {}, maxRecentPosts: int, translate: {}, pageNumber: int, itemsPerPage: int, diff --git a/webapp_utils.py b/webapp_utils.py index 2dcf172c..712ec5e7 100644 --- a/webapp_utils.py +++ b/webapp_utils.py @@ -437,6 +437,26 @@ def htmlHeader(cssFilename: str, css: str, lang='en') -> str: return htmlStr +def htmlHeaderWithExternalStyle(cssFilename: str, css: str, lang='en') -> str: + htmlStr = '\n' + htmlStr += '\n' + htmlStr += ' \n' + htmlStr += ' \n' + fontName, fontFormat = getFontFromCss(css) + if fontName: + htmlStr += ' \n' + htmlStr += ' \n' + cssFile = cssFilename.split('/')[-1] + htmlStr += ' ' + htmlStr += ' \n' + htmlStr += ' \n' + htmlStr += ' Epicyon\n' + htmlStr += ' \n' + htmlStr += ' \n' + return htmlStr + + def htmlFooter() -> str: htmlStr = ' \n' htmlStr += '\n'