1
0
Fork 0
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:
Simo Kinnunen 2014-07-04 22:59:29 +09:00
parent 332c7b6106
commit e13fc6701f
11 changed files with 152 additions and 141 deletions

View file

@ -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",

View file

@ -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({

View file

@ -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))

View file

@ -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'))

View file

@ -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
}

View file

@ -1,3 +1,3 @@
module.exports = function LayoutCtrl(LanguageService) {
LanguageService.init()
LanguageService.updateLanguage()
}

View file

@ -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 () {

View file

@ -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

View file

@ -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
}

View file

@ -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 ' +

View file

@ -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}}