mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	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:
		
				
					committed by
					
						
						techknowlogick
					
				
			
			
				
	
			
			
			
						parent
						
							e09fe48773
						
					
				
				
					commit
					294904321c
				
			
							
								
								
									
										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);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
		Reference in New Issue
	
	Block a user