* Create manifest and serviceworker
* Create templates and add AppSubUrl
* Add JSRenderer
* fix ctx type
* Add JSRenderer to static.go
* Complete adding {{AppSubUrl}}
* Add more fonts to urlsToCache
* Add 512px and 192px icons
* Hardcode font MD5
* Default theme doesn't have a specific CSS file
tags/v1.7.0-dev
| @@ -347,6 +347,8 @@ update-translations: | |||||
| generate-images: | generate-images: | ||||
| mkdir -p $(TMPDIR)/images | mkdir -p $(TMPDIR)/images | ||||
| inkscape -f $(PWD)/assets/logo.svg -w 880 -h 880 -e $(PWD)/public/img/gitea-lg.png | inkscape -f $(PWD)/assets/logo.svg -w 880 -h 880 -e $(PWD)/public/img/gitea-lg.png | ||||
| inkscape -f $(PWD)/assets/logo.svg -w 512 -h 512 -e $(PWD)/public/img/gitea-512.png | |||||
| inkscape -f $(PWD)/assets/logo.svg -w 192 -h 192 -e $(PWD)/public/img/gitea-192.png | |||||
| inkscape -f $(PWD)/assets/logo.svg -w 120 -h 120 -jC -i layer1 -e $(TMPDIR)/images/sm-1.png | inkscape -f $(PWD)/assets/logo.svg -w 120 -h 120 -jC -i layer1 -e $(TMPDIR)/images/sm-1.png | ||||
| inkscape -f $(PWD)/assets/logo.svg -w 120 -h 120 -jC -i layer2 -e $(TMPDIR)/images/sm-2.png | inkscape -f $(PWD)/assets/logo.svg -w 120 -h 120 -jC -i layer2 -e $(TMPDIR)/images/sm-2.png | ||||
| composite -compose atop $(TMPDIR)/images/sm-2.png $(TMPDIR)/images/sm-1.png $(PWD)/public/img/gitea-sm.png | composite -compose atop $(TMPDIR)/images/sm-2.png $(TMPDIR)/images/sm-1.png $(PWD)/public/img/gitea-sm.png | ||||
| @@ -45,6 +45,18 @@ func JSONRenderer() macaron.Handler { | |||||
| }) | }) | ||||
| } | } | ||||
| // JSRenderer implements the macaron handler for serving JS templates. | |||||
| func JSRenderer() macaron.Handler { | |||||
| return macaron.Renderer(macaron.RenderOptions{ | |||||
| Funcs: NewFuncMap(), | |||||
| Directory: path.Join(setting.StaticRootPath, "templates"), | |||||
| AppendDirectories: []string{ | |||||
| path.Join(setting.CustomPath, "templates"), | |||||
| }, | |||||
| HTMLContentType: "application/javascript", | |||||
| }) | |||||
| } | |||||
| // Mailer provides the templates required for sending notification mails. | // Mailer provides the templates required for sending notification mails. | ||||
| func Mailer() *template.Template { | func Mailer() *template.Template { | ||||
| for _, funcs := range NewFuncMap() { | for _, funcs := range NewFuncMap() { | ||||
| @@ -129,6 +129,15 @@ func JSONRenderer() macaron.Handler { | |||||
| }) | }) | ||||
| } | } | ||||
| // JSRenderer implements the macaron handler for serving JS templates. | |||||
| func JSRenderer() macaron.Handler { | |||||
| return macaron.Renderer(macaron.RenderOptions{ | |||||
| Funcs: NewFuncMap(), | |||||
| TemplateFileSystem: NewTemplateFileSystem(), | |||||
| HTMLContentType: "application/javascript", | |||||
| }) | |||||
| } | |||||
| // Mailer provides the templates required for sending notification mails. | // Mailer provides the templates required for sending notification mails. | ||||
| func Mailer() *template.Template { | func Mailer() *template.Template { | ||||
| for _, funcs := range NewFuncMap() { | for _, funcs := range NewFuncMap() { | ||||
| @@ -791,6 +791,15 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
| } | } | ||||
| }) | }) | ||||
| // Progressive Web App | |||||
| m.Get("/manifest.json", templates.JSONRenderer(), func(ctx *context.Context) { | |||||
| ctx.HTML(200, "pwa/manifest_json") | |||||
| }) | |||||
| m.Get("/serviceworker.js", templates.JSRenderer(), func(ctx *context.Context) { | |||||
| ctx.HTML(200, "pwa/serviceworker_js") | |||||
| }) | |||||
| // prometheus metrics endpoint | // prometheus metrics endpoint | ||||
| if setting.Metrics.Enabled { | if setting.Metrics.Enabled { | ||||
| c := metrics.NewCollector() | c := metrics.NewCollector() | ||||
| @@ -5,6 +5,23 @@ | |||||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | <meta name="viewport" content="width=device-width, initial-scale=1"> | ||||
| <meta http-equiv="x-ua-compatible" content="ie=edge"> | <meta http-equiv="x-ua-compatible" content="ie=edge"> | ||||
| <title>{{if .Title}}{{.Title}} - {{end}}{{AppName}}</title> | <title>{{if .Title}}{{.Title}} - {{end}}{{AppName}}</title> | ||||
| <link rel="manifest" href="{{AppSubUrl}}/manifest.json"> | |||||
| <script> | |||||
| if ('serviceWorker' in navigator) { | |||||
| window.addEventListener('load', function() { | |||||
| navigator.serviceWorker.register('{{AppSubUrl}}/serviceworker.js').then(function(registration) { | |||||
| // Registration was successful | |||||
| console.log('ServiceWorker registration successful with scope: ', registration.scope); | |||||
| }, function(err) { | |||||
| // registration failed :( | |||||
| console.log('ServiceWorker registration failed: ', err); | |||||
| }); | |||||
| }); | |||||
| } | |||||
| </script> | |||||
| <meta name="theme-color" content="{{ThemeColorMetaTag}}"> | <meta name="theme-color" content="{{ThemeColorMetaTag}}"> | ||||
| <meta name="author" content="{{if .Repository}}{{.Owner.Name}}{{else}}{{MetaAuthor}}{{end}}" /> | <meta name="author" content="{{if .Repository}}{{.Owner.Name}}{{else}}{{MetaAuthor}}{{end}}" /> | ||||
| <meta name="description" content="{{if .Repository}}{{.Repository.Name}}{{if .Repository.Description}} - {{.Repository.Description}}{{end}}{{else}}{{MetaDescription}}{{end}}" /> | <meta name="description" content="{{if .Repository}}{{.Repository.Name}}{{if .Repository.Description}} - {{.Repository.Description}}{{end}}{{else}}{{MetaDescription}}{{end}}" /> | ||||
| @@ -0,0 +1,31 @@ | |||||
| { | |||||
| "short_name": "Gitea", | |||||
| "name": "Gitea - Git with a cup of tea", | |||||
| "icons": [ | |||||
| { | |||||
| "src": "{{AppSubUrl}}/img/gitea-lg.png", | |||||
| "type": "image/png", | |||||
| "sizes": "880x880" | |||||
| }, | |||||
| { | |||||
| "src": "{{AppSubUrl}}/img/gitea-sm.png", | |||||
| "type": "image/png", | |||||
| "sizes": "120x120" | |||||
| }, | |||||
| { | |||||
| "src": "{{AppSubUrl}}/img/gitea-512.png", | |||||
| "type": "image/png", | |||||
| "sizes": "512x512" | |||||
| }, | |||||
| { | |||||
| "src": "{{AppSubUrl}}/img/gitea-192.png", | |||||
| "type": "image/png", | |||||
| "sizes": "192x192" | |||||
| } | |||||
| ], | |||||
| "start_url": "{{AppSubUrl}}/", | |||||
| "scope": "{{AppSubUrl}}/", | |||||
| "background_color": "#FAFAFA", | |||||
| "display": "standalone", | |||||
| "theme_color": "{{ThemeColorMetaTag}}" | |||||
| } | |||||
| @@ -0,0 +1,72 @@ | |||||
| var STATIC_CACHE = 'static-cache-v1'; | |||||
| var urlsToCache = [ | |||||
| // js | |||||
| '{{AppSubUrl}}/vendor/plugins/jquery.areyousure/jquery.are-you-sure.js', | |||||
| '{{AppSubUrl}}/vendor/plugins/jquery/jquery.min.js', | |||||
| '{{AppSubUrl}}/vendor/plugins/semantic/semantic.min.js', | |||||
| '{{AppSubUrl}}/js/index.js?v={{MD5 AppVer}}', | |||||
| '{{AppSubUrl}}/js/draw.js', | |||||
| '{{AppSubUrl}}/vendor/plugins/clipboard/clipboard.min.js', | |||||
| '{{AppSubUrl}}/vendor/plugins/gitgraph/gitgraph.js', | |||||
| '{{AppSubUrl}}/vendor/plugins/vue/vue.min.js', | |||||
| '{{AppSubUrl}}/vendor/plugins/emojify/emojify.min.js', | |||||
| '{{AppSubUrl}}/vendor/plugins/cssrelpreload/loadCSS.min.js', | |||||
| '{{AppSubUrl}}/vendor/plugins/cssrelpreload/cssrelpreload.min.js', | |||||
| '{{AppSubUrl}}/vendor/plugins/dropzone/dropzone.js', | |||||
| '{{AppSubUrl}}/vendor/plugins/highlight/highlight.pack.js', | |||||
| '{{AppSubUrl}}/vendor/plugins/jquery.datetimepicker/jquery.datetimepicker.js', | |||||
| '{{AppSubUrl}}/vendor/plugins/jquery.minicolors/jquery.minicolors.min.js', | |||||
| '{{AppSubUrl}}/vendor/plugins/codemirror/addon/mode/loadmode.js', | |||||
| '{{AppSubUrl}}/vendor/plugins/codemirror/mode/meta.js', | |||||
| '{{AppSubUrl}}/vendor/plugins/simplemde/simplemde.min.js', | |||||
| // css | |||||
| '{{AppSubUrl}}/vendor/assets/font-awesome/css/font-awesome.min.css', | |||||
| '{{AppSubUrl}}/vendor/assets/octicons/octicons.min.css', | |||||
| '{{AppSubUrl}}/vendor/plugins/simplemde/simplemde.min.css', | |||||
| '{{AppSubUrl}}/vendor/plugins/gitgraph/gitgraph.css', | |||||
| '{{AppSubUrl}}/vendor/plugins/tribute/tribute.css', | |||||
| '{{AppSubUrl}}/vendor/plugins/semantic/semantic.min.css', | |||||
| '{{AppSubUrl}}/css/index.css?v={{MD5 AppVer}}', | |||||
| '{{AppSubUrl}}/vendor/plugins/highlight/github.css', | |||||
| '{{AppSubUrl}}/vendor/plugins/jquery.minicolors/jquery.minicolors.css', | |||||
| '{{AppSubUrl}}/vendor/plugins/jquery.datetimepicker/jquery.datetimepicker.css', | |||||
| '{{AppSubUrl}}/vendor/plugins/dropzone/dropzone.css', | |||||
| {{if ne DefaultTheme "gitea"}} | |||||
| '{{AppSubUrl}}/css/theme-{{DefaultTheme}}.css', | |||||
| {{end}} | |||||
| // img | |||||
| '{{AppSubUrl}}/img/gitea-sm.png', | |||||
| '{{AppSubUrl}}/img/gitea-lg.png', | |||||
| // fonts | |||||
| '{{AppSubUrl}}/vendor/plugins/semantic/themes/default/assets/fonts/icons.woff2', | |||||
| '{{AppSubUrl}}/vendor/assets/octicons/octicons.woff2?ef21c39f0ca9b1b5116e5eb7ac5eabe6', | |||||
| '{{AppSubUrl}}/vendor/assets/lato-fonts/lato-v14-latin-regular.woff2', | |||||
| '{{AppSubUrl}}/vendor/assets/lato-fonts/lato-v14-latin-700.woff2' | |||||
| ]; | |||||
| self.addEventListener('install', function (event) { | |||||
| // Perform install steps | |||||
| event.waitUntil( | |||||
| caches.open(STATIC_CACHE) | |||||
| .then(function (cache) { | |||||
| return cache.addAll(urlsToCache); | |||||
| }) | |||||
| ); | |||||
| }); | |||||
| self.addEventListener('fetch', function (event) { | |||||
| event.respondWith( | |||||
| caches.match(event.request) | |||||
| .then(function (response) { | |||||
| // Cache hit - return response | |||||
| if (response) { | |||||
| return response; | |||||
| } | |||||
| return fetch(event.request); | |||||
| } | |||||
| ) | |||||
| ); | |||||
| }); | |||||