mirror of
https://github.com/openstf/stf
synced 2025-10-04 10:19:30 +02:00
Save user settings to the database and embed them to the template for fast access.
This commit is contained in:
parent
332c7b6106
commit
e13fc6701f
11 changed files with 152 additions and 141 deletions
|
@ -13,7 +13,6 @@
|
|||
"oboe": "~1.15.1",
|
||||
"fa-borderlayout": "~0.3.1-beta2",
|
||||
"Snap.svg": "~0.3.0",
|
||||
"angular-localForage": "~0.2.6",
|
||||
"ng-table": "git://github.com/esvit/ng-table.git#bd9ec42172389257fcd312330013302b2696ac2a",
|
||||
"jquery.terminal": "~0.8.7",
|
||||
"stf-site": "~0.4.1",
|
||||
|
|
|
@ -25,6 +25,7 @@ dbapi.saveUserAfterLogin = function(user) {
|
|||
, lastLoggedInAt: r.now()
|
||||
, createdAt: r.now()
|
||||
, forwards: []
|
||||
, settings: {}
|
||||
}))
|
||||
}
|
||||
return stats
|
||||
|
@ -35,6 +36,18 @@ dbapi.loadUser = function(email) {
|
|||
return db.run(r.table('users').get(email))
|
||||
}
|
||||
|
||||
dbapi.updateUserSettings = function(email, changes) {
|
||||
return db.run(r.table('users').get(email).update({
|
||||
settings: changes
|
||||
}))
|
||||
}
|
||||
|
||||
dbapi.resetUserSettings = function(email) {
|
||||
return db.run(r.table('users').get(email).update({
|
||||
settings: r.literal({})
|
||||
}))
|
||||
}
|
||||
|
||||
dbapi.addUserForward = function(email, forward) {
|
||||
var devicePort = forward.devicePort
|
||||
return db.run(r.table('users').get(email).update({
|
||||
|
|
|
@ -256,6 +256,13 @@ module.exports = function(options) {
|
|||
|
||||
new Promise(function(resolve) {
|
||||
socket.on('disconnect', resolve)
|
||||
// Settings
|
||||
.on('user.settings.update', function(data) {
|
||||
dbapi.updateUserSettings(user.email, data)
|
||||
})
|
||||
.on('user.settings.reset', function() {
|
||||
dbapi.resetUserSettings(user.email)
|
||||
})
|
||||
// Touch events
|
||||
.on('input.touchDown', createTouchHandler(wire.TouchDownMessage))
|
||||
.on('input.touchMove', createTouchHandler(wire.TouchMoveMessage))
|
||||
|
|
|
@ -1,17 +1,2 @@
|
|||
require('localforage')
|
||||
require('angular-localForage')
|
||||
|
||||
module.exports = angular.module('stf/settings', [
|
||||
'LocalForageModule'
|
||||
])
|
||||
.config(['$localForageProvider', function ($localForageProvider) {
|
||||
$localForageProvider.config({
|
||||
driver: 'localStorageWrapper',
|
||||
name: 'stf-v0',
|
||||
version: 1.0,
|
||||
storeName: 'settings',
|
||||
description: 'STF Local Settings'
|
||||
})
|
||||
|
||||
}])
|
||||
module.exports = angular.module('stf/settings', [])
|
||||
.factory('SettingsService', require('./settings-service'))
|
||||
|
|
|
@ -1,61 +1,103 @@
|
|||
var Promise = require('bluebird')
|
||||
var _ = require('lodash')
|
||||
|
||||
module.exports = function SettingsServiceFactory($localForage) {
|
||||
module.exports = function SettingsServiceFactory(
|
||||
$rootScope
|
||||
, UserService
|
||||
, socket
|
||||
) {
|
||||
var SettingsService = {}
|
||||
|
||||
var loadedInMemory = false
|
||||
var settings = UserService.currentUser.settings || {}
|
||||
, syncListeners = []
|
||||
|
||||
var memoryData = Object.create(null)
|
||||
function createListener(object, options, monitor) {
|
||||
var source = options.source || options.target
|
||||
return function() {
|
||||
var value = object[options.target] = (source in settings)
|
||||
? settings[source]
|
||||
: options.defaultValue
|
||||
|
||||
function setItemMemory(key, value) {
|
||||
memoryData[key] = value
|
||||
}
|
||||
|
||||
function getItemMemory(key) {
|
||||
return memoryData[key]
|
||||
}
|
||||
|
||||
SettingsService.setItem = function (key, value) {
|
||||
setItemMemory(key, value)
|
||||
return $localForage.setItem(key, value)
|
||||
}
|
||||
|
||||
function loadAllItems() {
|
||||
if (loadedInMemory) {
|
||||
return Promise.resolve()
|
||||
if (monitor) {
|
||||
monitor(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $localForage.getKeys().then(function (keys) {
|
||||
return Promise.all(keys.map(function (key) {
|
||||
return $localForage.getItem(key).then(setItemMemory.bind(null, key))
|
||||
}))
|
||||
}).then(function () {
|
||||
loadedInMemory = true
|
||||
function applyDelta(delta) {
|
||||
$rootScope.safeApply(function() {
|
||||
_.merge(settings, delta, function(a, b) {
|
||||
// New Arrays overwrite old Arrays
|
||||
return _.isArray(b) ? b : undefined
|
||||
})
|
||||
|
||||
for (var i = 0, l = syncListeners.length; i < l; ++i) {
|
||||
syncListeners[i]()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
SettingsService.getItem = function (key) {
|
||||
return loadAllItems().then(function () {
|
||||
return getItemMemory(key)
|
||||
})
|
||||
SettingsService.update = function(delta) {
|
||||
socket.emit('user.settings.update', delta)
|
||||
applyDelta(delta)
|
||||
}
|
||||
|
||||
SettingsService.bind = function () {
|
||||
|
||||
|
||||
|
||||
return $localForage.bind.apply($localForage, arguments)
|
||||
SettingsService.set = function(key, value) {
|
||||
var delta = Object.create(null)
|
||||
delta[key] = value
|
||||
SettingsService.update(delta)
|
||||
}
|
||||
|
||||
SettingsService.driver = function () {
|
||||
return $localForage.driver.apply($localForage, arguments)
|
||||
+ ' with memory cache'
|
||||
SettingsService.reset = function() {
|
||||
socket.emit('user.settings.reset')
|
||||
settings = {}
|
||||
applyDelta(null)
|
||||
}
|
||||
|
||||
SettingsService.clear = function () {
|
||||
memoryData = Object.create(null)
|
||||
return $localForage.clear.apply($localForage, arguments)
|
||||
SettingsService.bind = function(scope, options) {
|
||||
var source = options.source || options.target
|
||||
|
||||
scope.$watch(
|
||||
options.target
|
||||
, function(newValue, oldValue) {
|
||||
// Skip initial value.
|
||||
if (newValue !== oldValue) {
|
||||
var delta = Object.create(null)
|
||||
delta[source] = newValue
|
||||
SettingsService.update(delta)
|
||||
}
|
||||
}
|
||||
, true
|
||||
)
|
||||
|
||||
scope.$watch(
|
||||
function() {
|
||||
return settings[source]
|
||||
}
|
||||
, function(newValue, oldValue) {
|
||||
// Skip initial value. The new value might not be different if
|
||||
// settings were reset, for example. In that case we call back
|
||||
// to the default value.
|
||||
if (newValue !== oldValue) {
|
||||
scope[options.target] = newValue || options.defaultValue
|
||||
}
|
||||
}
|
||||
, true
|
||||
)
|
||||
|
||||
scope[options.target] = settings[source] || options.defaultValue
|
||||
}
|
||||
|
||||
SettingsService.sync = function(object, options, monitor) {
|
||||
var listener = createListener(object, options, monitor)
|
||||
listener() // Initialize
|
||||
return syncListeners.push(listener) - 1
|
||||
}
|
||||
|
||||
SettingsService.unsync = function(id) {
|
||||
syncListeners.splice(id, 1)
|
||||
}
|
||||
|
||||
socket.on('user.settings.update', applyDelta)
|
||||
|
||||
return SettingsService
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
module.exports = function LayoutCtrl(LanguageService) {
|
||||
LanguageService.init()
|
||||
LanguageService.updateLanguage()
|
||||
}
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
module.exports = function MenuCtrl($scope, $rootScope, SettingsService, $location, ExternalUrlModalService) {
|
||||
$rootScope.platform = 'native'
|
||||
module.exports = function MenuCtrl(
|
||||
$scope
|
||||
, $rootScope
|
||||
, SettingsService
|
||||
, $location
|
||||
, ExternalUrlModalService
|
||||
) {
|
||||
SettingsService.bind($rootScope, {
|
||||
key: 'platform',
|
||||
storeName: 'Platform'
|
||||
target: 'platform'
|
||||
, defaultValue: 'native'
|
||||
})
|
||||
|
||||
$scope.$on('$routeChangeSuccess', function () {
|
||||
|
|
|
@ -1,20 +1,8 @@
|
|||
module.exports = function ($scope, LanguageService, SettingsService) {
|
||||
// SettingsService.sync($scope, 'Language', {
|
||||
// language: LanguageService.detectedLanguage
|
||||
// })
|
||||
// SettingsService.bind($scope, {
|
||||
// key: 'language',
|
||||
// defaultValue: LanguageService.selectedLanguage
|
||||
// })
|
||||
|
||||
LanguageService.getSelectedLanguage().then(function (data) {
|
||||
$scope.language = data
|
||||
})
|
||||
|
||||
$scope.$watch('language', function (newValue, oldValue) {
|
||||
if (newValue !== oldValue) {
|
||||
LanguageService.setSelectedLanguage(newValue)
|
||||
}
|
||||
SettingsService.bind($scope, {
|
||||
target: 'language'
|
||||
, source: LanguageService.settingKey
|
||||
, defaultValue: LanguageService.detectedLanguage
|
||||
})
|
||||
|
||||
$scope.supportedLanguages = LanguageService.supportedLanguages
|
||||
|
|
|
@ -1,67 +1,45 @@
|
|||
var _ = require('lodash')
|
||||
var supportedLanguages = require('./../../../common/lang/langs.json')
|
||||
|
||||
module.exports = function (SettingsService, $q, gettextCatalog) {
|
||||
module.exports = function LanguageServiceFactory(
|
||||
SettingsService
|
||||
, gettextCatalog
|
||||
) {
|
||||
var LanguageService = {}
|
||||
|
||||
function detectLanguage() {
|
||||
return (navigator.language || navigator.userLanguage || 'en-US')
|
||||
.substring(0, 2)
|
||||
}
|
||||
|
||||
function isSupported(lang) {
|
||||
return !!supportedLanguages[lang]
|
||||
}
|
||||
|
||||
function onlySupported(lang, defaultValue) {
|
||||
return isSupported(lang) ? lang : defaultValue
|
||||
}
|
||||
|
||||
LanguageService.settingKey = 'selectedLanguage'
|
||||
LanguageService.supportedLanguages = supportedLanguages
|
||||
LanguageService.defaultLanguage = 'en'
|
||||
LanguageService.detectedLanguage =
|
||||
onlySupported(detectLanguage(), LanguageService.defaultLanguage)
|
||||
|
||||
var browserLocale = navigator.language || navigator.userLanguage || 'en-US'
|
||||
var browserLanguage = browserLocale.substring(0, 2)
|
||||
var isLanguageMatched = _.some(supportedLanguages, function (value, key) {
|
||||
return key === browserLanguage
|
||||
})
|
||||
var detectedLanguage = isLanguageMatched ? browserLanguage : 'en'
|
||||
|
||||
var defaultLanguage = 'ja'
|
||||
LanguageService.detectedLanguage = defaultLanguage
|
||||
LanguageService.selectedLanguage = null
|
||||
|
||||
// TODO: Can't this be refactored to something like this?
|
||||
// SettingsService.sync(LanguageService.selectedLanguage, 'Language', {
|
||||
// selected: LanguageService.detectedLanguage
|
||||
// })
|
||||
|
||||
LanguageService.getSelectedLanguage = function () {
|
||||
var deferred = $q.defer()
|
||||
if (LanguageService.selectedLanguage) {
|
||||
deferred.resolve(LanguageService.selectedLanguage)
|
||||
} else {
|
||||
SettingsService.getItem('Language.selected').then(function (data) {
|
||||
if (data) {
|
||||
deferred.resolve(data)
|
||||
} else {
|
||||
LanguageService.setSelectedLanguage(LanguageService.detectedLanguage)
|
||||
.then(function () {
|
||||
deferred.resolve(LanguageService.detectedLanguage)
|
||||
})
|
||||
}
|
||||
})
|
||||
SettingsService.sync(
|
||||
LanguageService
|
||||
, {
|
||||
target: LanguageService.settingKey
|
||||
, source: LanguageService.settingKey
|
||||
, defaultValue: LanguageService.detectedLanguage
|
||||
}
|
||||
return deferred.promise
|
||||
, updateLanguage
|
||||
)
|
||||
|
||||
function updateLanguage() {
|
||||
gettextCatalog.currentLanguage = LanguageService.selectedLanguage
|
||||
}
|
||||
|
||||
// TODO: this is to prevent initial text flashing from ja
|
||||
gettextCatalog.currentLanguage = LanguageService.detectedLanguage
|
||||
|
||||
// Initialize gettextCatalog
|
||||
|
||||
LanguageService.init = function () {
|
||||
LanguageService.getSelectedLanguage().then(function (data) {
|
||||
LanguageService.setSelectedLanguage(data)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
LanguageService.setSelectedLanguage = function (lang) {
|
||||
var deferred = $q.defer()
|
||||
LanguageService.selectedLanguage = lang
|
||||
gettextCatalog.currentLanguage = lang
|
||||
SettingsService.setItem('Language.selected', lang).then(function () {
|
||||
deferred.resolve(lang)
|
||||
})
|
||||
return deferred.promise
|
||||
}
|
||||
LanguageService.updateLanguage = updateLanguage
|
||||
|
||||
return LanguageService
|
||||
}
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
module.exports = function ($scope, SettingsService) {
|
||||
|
||||
$scope.resetSettings = function () {
|
||||
SettingsService.clear()
|
||||
SettingsService.reset()
|
||||
console.log('Settings cleared')
|
||||
}
|
||||
|
||||
$scope.savedTo = SettingsService.driver()
|
||||
|
||||
// $scope.resetSettings = function () {
|
||||
// var title = 'Reset Settings';
|
||||
// var msg = 'Are you sure you want to revert all settings to ' +
|
||||
|
|
|
@ -6,6 +6,3 @@
|
|||
button(ng-click='resetSettings()').btn.btn-danger
|
||||
i.fa.fa-trash-o
|
||||
span(translate) Reset Settings
|
||||
|
||||
p
|
||||
span.text-muted(translate) Saved to: {{savedTo}}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue