diff --git a/assets/css/default.css b/assets/css/default.css index a47762ec..9c933b39 100644 --- a/assets/css/default.css +++ b/assets/css/default.css @@ -443,31 +443,68 @@ p.video-data { margin: 0; font-weight: bold; font-size: 80%; } */ footer { - margin-top: auto; + color: #919191; + margin-top: 2.5em; padding: 1.5em 0; - text-align: center; - max-height: 30vh; } -.light-theme footer { - color: #7c7c7c; +#footer-content-container { + display: flex; + flex-direction: column; + gap: 20px; } -.dark-theme footer { - color: #adadad; +#footer-content-container > hr { + margin: 0; + color: rgb(241, 241, 241); } -.light-theme footer a { - color: #7c7c7c !important; +.footer-content { + display: flex; + justify-content: space-between; + flex-wrap: wrap; + margin-top: -10px; } -.dark-theme footer a { - color: #adadad !important; +footer a { + color: #919191; } -footer span { - margin: 4px 0; - display: block; +.footer-content #footer-custom-text > b { + font-size: 30px; +} + +.footer-section { + margin-right: 20px; + margin-top: 20px; +} + +.footer-section-list { + margin-top: 8px; +} + +.footer-section-item { + margin-bottom: 4px; +} + +.footer-footer .left { + float: left +} + +.footer-footer .right { + float: right; + display: flex; + gap: 5px; +} + +.footer-right .right a { + color: #919191 +} + +@media screen and (max-width: 929px) { + #footer-custom-text { + display: none; + } } /* keyframes */ @@ -533,6 +570,23 @@ span > select { color: #565d64; } +.light-theme footer { + color: #7a7a7a; + background: #f2f2f2; +} + +.light-theme #footer-content-container > hr { + color: rgb(241, 241, 241); +} + +.light-theme footer a { + color: #7c7c7c !important; +} + +.light-theme footer #footer-custom-text > b { + color: #565D64; +} + @media (prefers-color-scheme: light) { .no-theme a:hover, .no-theme a:active, @@ -568,17 +622,22 @@ span > select { color: #303030; } + .light-theme .pure-menu-heading { + color: #565d64; + } + .no-theme footer { + background: #f2f2f2; color: #7c7c7c; } + + .no-theme footer #footer-custom-text > b { + color: #565D64; + } .no-theme footer a { color: #7c7c7c !important; } - - .light-theme .pure-menu-heading { - color: #565d64; - } } @@ -641,6 +700,20 @@ body.dark-theme { color: inherit; } + +.dark-theme footer { + background: #16191a; +} + +.dark-theme #footer-content-container > hr { + color: #313131; +} + +.dark-theme .footer-content #footer-custom-text > b { + color: #ccc; +} + + @media (prefers-color-scheme: dark) { .no-theme a:hover, .no-theme a:active, @@ -696,11 +769,12 @@ body.dark-theme { } .no-theme footer { - color: #adadad; + background: #16191a; + color: #313131; } - .no-theme footer a { - color: #adadad !important; + .no-theme footer #footer-custom-text > b { + color: #ccc; } } @@ -786,6 +860,17 @@ h1, h2, h3, h4, h5, p, /* Center the "invidious" logo on the search page */ #logo > h1 { text-align: center; } +#footer_buffer { + margin-top: 50vh; +} + +@media screen and (max-width: 450px) { + #footer_buffer { + display: none; + } +} + + /* IE11 fixes */ :-ms-input-placeholder { color: #888; } diff --git a/config/config.example.yml b/config/config.example.yml index 38085a20..b3e8a09b 100644 --- a/config/config.example.yml +++ b/config/config.example.yml @@ -391,9 +391,8 @@ jobs: ## enable: true - # ----------------------------- -# Miscellaneous +# Instance customization # ----------------------------- ## @@ -405,6 +404,78 @@ jobs: ## #banner: +## +## custom text displayed at the bottom of every page within Invidious' footer. This can +## used for instance announcements, e.g +## +## When unset Invidious defaults to some text that describes what Invidious is. See +## localization key default_invidious_footer_text +## +## Accepted values: any string. HTML is accepted. +## Default: +## +#footer: + +## +## Source code URL. If your instance is running a modified source +## code, you MUST publish it somewhere and set this option. +## +## Accepted values: a string +## Default: +## +#modified_source_code_url: "" + +## +## Email to contact the instance maintainer; used in a mailto: link within the footer. +## +## Accepted values: string +## Default: +## +# instance_maintainer_email: + +## +## Link to the terms of service of the instance (if any) +## +## Displayed within the instance section of the footer +## +## Accepted values: String (link) +## Default: +## +# footer_instance_tos_link: + +## +## Link to the privacy-policy of the instance (if any) +## +## Displayed within the instance section of the footer +## +## Accepted values: String (link) +## Default: +## +# footer_instance_privacy_policy_link: + +## +## Instance donation URL. If your instance has a donation option. +## you can add it here so it will be present in the footer along +## with the donation link for the project itself. +## +## Accepted values: a string +## Default: +## +#footer_instance_donate_link: "" + +## +## Custom fields to be displayed within the footer's instance section +## +## Accepted values: A nested array mapping field name and links together. +## IE: [ ["field1", "https://example.com/1"], ["field2", "https://example.com/2"] ] +## Default: +## +# footer_instance_section_custom_fields: [] + +# ----------------------------- +# Miscellaneous +# ----------------------------- + ## ## Subscribe to channels using PubSubHub (Google PubSubHubbub service). ## PubSubHub allows Invidious to be instantly notified when a new video @@ -458,15 +529,6 @@ hmac_key: "CHANGE_ME!!" ## #cache_annotations: false -## -## Source code URL. If your instance is running a modified source -## code, you MUST publish it somewhere and set this option. -## -## Accepted values: a string -## Default: -## -#modified_source_code_url: "" - ## ## Maximum custom playlist length limit. ## @@ -475,6 +537,7 @@ hmac_key: "CHANGE_ME!!" ## #playlist_length_limit: 500 + ######################################### # # Default user preferences diff --git a/locales/en-US.json b/locales/en-US.json index 3987f796..ec6a23c9 100644 --- a/locales/en-US.json +++ b/locales/en-US.json @@ -458,14 +458,32 @@ "search_filters_sort_option_views": "View count", "search_filters_apply_button": "Apply selected filters", "Current version: ": "Current version: ", + "footer_current_version_modified": "Current version (modified): ", "next_steps_error_message": "After which you should try to: ", "next_steps_error_message_refresh": "Refresh", "next_steps_error_message_go_to_youtube": "Go to YouTube", - "footer_donate_page": "Donate", - "footer_documentation": "Documentation", - "footer_source_code": "Source code", - "footer_original_source_code": "Original source code", - "footer_modfied_source_code": "Modified source code", + "default_invidious_footer_text": "A free and open source frontend for Youtube that that respects your privacy! Now you can watch videos (ad-free), subscribe to channels, create playlist and much more all without the prying eyes of Google!", + "footer_navigation_section_header": "Navigation", + "footer_home_link": "Home", + "footer_project_information_section_header": "Invidious", + "footer_project_homepage_link": "Project Homepage", + "footer_source_code_link": "Source Code", + "footer_issue_tracker_link": "Issue tracker", + "footer_public_instances_link": "Public instances", + "footer_donate_link": "Donate", + "footer_matrix_link": "Matrix", + "footer_support_section_header": "Support", + "footer_contact_link": "Contact Instance Maintainer", + "footer_report_bug_link": "Report a bug", + "footer_faq_link": "FAQ", + "footer_instance_section_header": "Instance", + "footer_instance_section_header_modified_source": "Instance (Modified)", + "footer_instance_section_modified_source_code": "Instance Source Code", + "footer_instance_section_tos": "Terms of Service", + "footer_instance_section_privacy_policy": "Privacy Policy", + "footer_instance_section_donate": "Donate (Instance)", + "footer_licences_link": "Licences", + "footer_privacy_policy_link": "Privacy", "adminprefs_modified_source_code_url_label": "URL to modified source code repository", "none": "none", "videoinfo_started_streaming_x_ago": "Started streaming `x` ago", diff --git a/src/invidious/config.cr b/src/invidious/config.cr index 09c2168b..50677546 100644 --- a/src/invidious/config.cr +++ b/src/invidious/config.cr @@ -104,8 +104,6 @@ class Config property check_tables : Bool = false # Cache annotations requested from IA, will not cache empty annotations or annotations that only contain cards property cache_annotations : Bool = false - # Optional banner to be displayed along top of page for announcements, etc. - property banner : String? = nil # Enables 'Strict-Transport-Security'. Ensure that `domain` and all subdomains are served securely property hsts : Bool? = true # Disable proxying server-wide: options: 'dash', 'livestreams', 'downloads', 'local' @@ -113,9 +111,23 @@ class Config # Enable the user notifications for all users property enable_user_notifications : Bool = true + # Optional banner to be displayed along top of page for announcements, etc. + property banner : String? = nil + # Optional footer text to be displayed within Invidious' footer. Can be used for maintainer contact info, etc. + property footer : String? = nil + # Email to contact the instance maintainer. This is used within the footer as an mailto link. + property instance_maintainer_email : String? = nil # URL to the modified source code to be easily AGPL compliant - # Will display in the footer, next to the main source code link + # Will display in the footer property modified_source_code_url : String? = nil + # Link to the terms of service of the instance (if any). Will be displayed in the footer. + property footer_instance_tos_link : String? = nil + # Link to the privacy policy of the instance (if any). Will be displayed in the footer. + property footer_instance_privacy_policy_link : String? = nil + # Instance donation URL displayed in the "Instance" section of the footer + property footer_instance_donate_link : String? = nil + # Custom fields to be displayed within the footer's instance section + property footer_instance_section_custom_fields : Array(Array(String)) = [] of Array(String) # Connect to YouTube over 'ipv6', 'ipv4'. Will sometimes resolve fix issues with rate-limiting (see https://github.com/ytdl-org/youtube-dl/issues/21729) @[YAML::Field(converter: Preferences::FamilyConverter)] diff --git a/src/invidious/helpers/macros.cr b/src/invidious/helpers/macros.cr index 43e7171b..d55fa6fc 100644 --- a/src/invidious/helpers/macros.cr +++ b/src/invidious/helpers/macros.cr @@ -48,8 +48,9 @@ module JSON::Serializable end end -macro templated(_filename, template = "template", navbar_search = true) +macro templated(_filename, template = "template", navbar_search = true, buffer_footer = false) navbar_search = {{navbar_search}} + buffer_footer = {{buffer_footer}} {{ filename = "src/invidious/views/" + _filename + ".ecr" }} {{ layout = "src/invidious/views/" + template + ".ecr" }} diff --git a/src/invidious/routes/channels.cr b/src/invidious/routes/channels.cr index 360af2cd..2201f3fa 100644 --- a/src/invidious/routes/channels.cr +++ b/src/invidious/routes/channels.cr @@ -114,7 +114,7 @@ module Invidious::Routes::Channels items.each(&.author = "") selected_tab = Frontend::ChannelPage::TabsAvailable::Playlists - templated "channel" + templated "channel", buffer_footer: true end def self.podcasts(env) diff --git a/src/invidious/routes/preferences.cr b/src/invidious/routes/preferences.cr index 05bc2714..84891fb4 100644 --- a/src/invidious/routes/preferences.cr +++ b/src/invidious/routes/preferences.cr @@ -8,7 +8,7 @@ module Invidious::Routes::PreferencesRoute preferences = env.get("preferences").as(Preferences) - templated "user/preferences" + templated "user/preferences", buffer_footer: true end def self.update(env) diff --git a/src/invidious/views/template.ecr b/src/invidious/views/template.ecr index 9904b4fc..1c33ec84 100644 --- a/src/invidious/views/template.ecr +++ b/src/invidious/views/template.ecr @@ -112,47 +112,9 @@ <%= content %> - + <% if buffer_footer %> + + <% end %> @@ -172,6 +134,176 @@ <% end %> <% end %> + +