Archived
Add support for themes (fixes #1925)
This commit is contained in:
1 parent
6c0a973ac3
commit
cd54186113
128 files changed
+205
-138
No files matched your search
@@ -410,7 +410,7 @@ func xdr() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func translate() {
|
func translate() {
|
||||||
os.Chdir("gui/assets/lang")
|
os.Chdir("gui/default/assets/lang")
|
||||||
runPipe("lang-en-new.json", "go", "run", "../../../script/translate.go", "lang-en.json", "../../")
|
runPipe("lang-en-new.json", "go", "run", "../../../script/translate.go", "lang-en.json", "../../")
|
||||||
os.Remove("lang-en.json")
|
os.Remove("lang-en.json")
|
||||||
err := os.Rename("lang-en-new.json", "lang-en.json")
|
err := os.Rename("lang-en-new.json", "lang-en.json")
|
||||||
@@ -421,7 +421,7 @@ func translate() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func transifex() {
|
func transifex() {
|
||||||
os.Chdir("gui/assets/lang")
|
os.Chdir("gui/default/assets/lang")
|
||||||
runPrint("go", "run", "../../../script/transifexdl.go")
|
runPrint("go", "run", "../../../script/transifexdl.go")
|
||||||
os.Chdir("../../..")
|
os.Chdir("../../..")
|
||||||
assets()
|
assets()
|
||||||
|
|||||||
+60
-11
@@ -52,6 +52,7 @@ type apiService struct {
|
|||||||
id protocol.DeviceID
|
id protocol.DeviceID
|
||||||
cfg *config.Wrapper
|
cfg *config.Wrapper
|
||||||
assetDir string
|
assetDir string
|
||||||
|
themes []string
|
||||||
model *model.Model
|
model *model.Model
|
||||||
eventSub *events.BufferedSubscription
|
eventSub *events.BufferedSubscription
|
||||||
discoverer *discover.CachingMux
|
discoverer *discover.CachingMux
|
||||||
@@ -79,6 +80,15 @@ func newAPIService(id protocol.DeviceID, cfg *config.Wrapper, assetDir string, m
|
|||||||
systemLog: systemLog,
|
systemLog: systemLog,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
seen := make(map[string]struct{})
|
||||||
|
for file := range auto.Assets() {
|
||||||
|
theme := strings.Split(file, "/")[0]
|
||||||
|
if _, ok := seen[theme]; !ok {
|
||||||
|
seen[theme] = struct{}{}
|
||||||
|
service.themes = append(service.themes, theme)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
service.listener, err = service.getListener(cfg.GUI())
|
service.listener, err = service.getListener(cfg.GUI())
|
||||||
return service, err
|
return service, err
|
||||||
@@ -198,10 +208,16 @@ func (s *apiService) Serve() {
|
|||||||
mux.HandleFunc("/qr/", s.getQR)
|
mux.HandleFunc("/qr/", s.getQR)
|
||||||
|
|
||||||
// Serve compiled in assets unless an asset directory was set (for development)
|
// Serve compiled in assets unless an asset directory was set (for development)
|
||||||
mux.Handle("/", embeddedStatic{
|
assets := &embeddedStatic{
|
||||||
assetDir: s.assetDir,
|
theme: s.cfg.GUI().Theme,
|
||||||
assets: auto.Assets(),
|
lastModified: time.Now(),
|
||||||
})
|
mut: sync.NewRWMutex(),
|
||||||
|
assetDir: s.assetDir,
|
||||||
|
assets: auto.Assets(),
|
||||||
|
}
|
||||||
|
mux.Handle("/", assets)
|
||||||
|
|
||||||
|
s.cfg.Subscribe(assets)
|
||||||
|
|
||||||
guiCfg := s.cfg.GUI()
|
guiCfg := s.cfg.GUI()
|
||||||
|
|
||||||
@@ -690,6 +706,7 @@ func (s *apiService) getSystemStatus(w http.ResponseWriter, r *http.Request) {
|
|||||||
res["pathSeparator"] = string(filepath.Separator)
|
res["pathSeparator"] = string(filepath.Separator)
|
||||||
res["uptime"] = int(time.Since(startTime).Seconds())
|
res["uptime"] = int(time.Since(startTime).Seconds())
|
||||||
res["startTime"] = startTime
|
res["startTime"] = startTime
|
||||||
|
res["themes"] = s.themes
|
||||||
|
|
||||||
sendJSON(w, res)
|
sendJSON(w, res)
|
||||||
}
|
}
|
||||||
@@ -1015,8 +1032,11 @@ func (s *apiService) getSystemBrowse(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type embeddedStatic struct {
|
type embeddedStatic struct {
|
||||||
assetDir string
|
theme string
|
||||||
assets map[string][]byte
|
lastModified time.Time
|
||||||
|
mut sync.RWMutex
|
||||||
|
assetDir string
|
||||||
|
assets map[string][]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s embeddedStatic) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (s embeddedStatic) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -1039,13 +1059,21 @@ func (s embeddedStatic) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bs, ok := s.assets[file]
|
s.mut.RLock()
|
||||||
|
theme := s.theme
|
||||||
|
modified := s.lastModified
|
||||||
|
s.mut.RUnlock()
|
||||||
|
|
||||||
|
bs, ok := s.assets[theme+"/"+file]
|
||||||
if !ok {
|
if !ok {
|
||||||
http.NotFound(w, r)
|
bs, ok = s.assets[config.DefaultTheme+"/"+file]
|
||||||
return
|
if !ok {
|
||||||
|
http.NotFound(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.Header.Get("If-Modified-Since") == auto.AssetsBuildDate {
|
if modifiedSince, err := time.Parse(r.Header.Get("If-Modified-Since"), http.TimeFormat); err == nil && modified.Before(modifiedSince) {
|
||||||
w.WriteHeader(http.StatusNotModified)
|
w.WriteHeader(http.StatusNotModified)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -1064,7 +1092,7 @@ func (s embeddedStatic) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
gr.Close()
|
gr.Close()
|
||||||
}
|
}
|
||||||
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(bs)))
|
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(bs)))
|
||||||
w.Header().Set("Last-Modified", auto.AssetsBuildDate)
|
w.Header().Set("Last-Modified", modified.Format(http.TimeFormat))
|
||||||
w.Header().Set("Cache-Control", "public")
|
w.Header().Set("Cache-Control", "public")
|
||||||
|
|
||||||
w.Write(bs)
|
w.Write(bs)
|
||||||
@@ -1097,6 +1125,27 @@ func (s embeddedStatic) mimeTypeForFile(file string) string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VerifyConfiguration implements the config.Committer interface
|
||||||
|
func (s *embeddedStatic) VerifyConfiguration(from, to config.Configuration) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CommitConfiguration implements the config.Committer interface
|
||||||
|
func (s *embeddedStatic) CommitConfiguration(from, to config.Configuration) bool {
|
||||||
|
s.mut.Lock()
|
||||||
|
if s.theme != to.GUI.Theme {
|
||||||
|
s.theme = to.GUI.Theme
|
||||||
|
s.lastModified = time.Now()
|
||||||
|
}
|
||||||
|
s.mut.Unlock()
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *embeddedStatic) String() string {
|
||||||
|
return fmt.Sprintf("embeddedStatic@%p", s)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *apiService) toNeedSlice(fs []db.FileInfoTruncated) []jsonDBFileInfo {
|
func (s *apiService) toNeedSlice(fs []db.FileInfoTruncated) []jsonDBFileInfo {
|
||||||
res := make([]jsonDBFileInfo, len(fs))
|
res := make([]jsonDBFileInfo, len(fs))
|
||||||
for i, f := range fs {
|
for i, f := range fs {
|
||||||
|
|||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+5
@@ -866,6 +866,7 @@ angular.module('syncthing.core')
|
|||||||
$scope.saveSettings = function () {
|
$scope.saveSettings = function () {
|
||||||
// Make sure something changed
|
// Make sure something changed
|
||||||
var changed = !angular.equals($scope.config.options, $scope.tmpOptions) || !angular.equals($scope.config.gui, $scope.tmpGUI);
|
var changed = !angular.equals($scope.config.options, $scope.tmpOptions) || !angular.equals($scope.config.gui, $scope.tmpGUI);
|
||||||
|
var themeChanged = $scope.config.gui.theme !== $scope.tmpGUI.theme;
|
||||||
if (changed) {
|
if (changed) {
|
||||||
// Check if usage reporting has been enabled or disabled
|
// Check if usage reporting has been enabled or disabled
|
||||||
if ($scope.tmpOptions.urEnabled && $scope.tmpOptions.urAccepted <= 0) {
|
if ($scope.tmpOptions.urEnabled && $scope.tmpOptions.urAccepted <= 0) {
|
||||||
@@ -901,6 +902,10 @@ angular.module('syncthing.core')
|
|||||||
}
|
}
|
||||||
|
|
||||||
$('#settings').modal("hide");
|
$('#settings').modal("hide");
|
||||||
|
|
||||||
|
if (themeChanged) {
|
||||||
|
document.location.reload(true);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.saveAdvanced = function () {
|
$scope.saveAdvanced = function () {
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+10
-1
@@ -136,8 +136,17 @@
|
|||||||
<span class="fa fa-repeat"></span> <span translate>Generate</span>
|
<span class="fa fa-repeat"></span> <span translate>Generate</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
|
<div class="form-group" ng-if="system.themes.length > 1">
|
||||||
|
<label>GUI Theme</label>
|
||||||
|
<select class="form-control" ng-model="tmpGUI.theme" ng->
|
||||||
|
<option ng-repeat="theme in system.themes" value="{{ theme }}">
|
||||||
|
{{ theme.charAt(0).toUpperCase() + theme.slice(1) }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loaded 100 of 128 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user