Create Progressive Web App (#4730)
* 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
			
			
This commit is contained in:
		
							parent
							
								
									e09fe48773
								
							
						
					
					
						commit
						294904321c
					
				
					 9 changed files with 152 additions and 0 deletions
				
			
		
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							|  | @ -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() { | ||||||
|  |  | ||||||
							
								
								
									
										
											BIN
										
									
								
								public/img/gitea-192.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/img/gitea-192.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 8.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								public/img/gitea-512.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/img/gitea-512.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 25 KiB | 
|  | @ -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}}" /> | ||||||
|  |  | ||||||
							
								
								
									
										31
									
								
								templates/pwa/manifest_json.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								templates/pwa/manifest_json.tmpl
									
									
									
									
									
										Normal file
									
								
							|  | @ -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}}" | ||||||
|  |   } | ||||||
							
								
								
									
										72
									
								
								templates/pwa/serviceworker_js.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								templates/pwa/serviceworker_js.tmpl
									
									
									
									
									
										Normal file
									
								
							|  | @ -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); | ||||||
|  |       } | ||||||
|  |       ) | ||||||
|  |   ); | ||||||
|  | }); | ||||||
		Loading…
	
		Reference in a new issue