diff --git a/.gitignore b/.gitignore index 25307818b..247b54065 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ dist/*.js.map dist/*.tar.gz public/css/*.css public/css/*.map +public/css/themes/* release/ # Node stuff diff --git a/index.html b/index.html index 9cb4e8c31..c7638dc19 100644 --- a/index.html +++ b/index.html @@ -53,7 +53,7 @@ - + diff --git a/package-lock.json b/package-lock.json index 64310efe2..eb8b8395a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1275,14 +1275,14 @@ } }, "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", + "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", + "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, "ajv-errors": { @@ -1418,40 +1418,6 @@ "requires": { "delegates": "^1.0.0", "readable-stream": "^2.0.6" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "argparse": { @@ -1752,7 +1718,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "optional": true, "requires": { "tweetnacl": "^0.14.3" }, @@ -1760,8 +1725,7 @@ "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "optional": true + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" } } }, @@ -2808,7 +2772,8 @@ "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true }, "code-point-at": { "version": "1.1.0", @@ -2853,9 +2818,9 @@ } }, "combined-stream": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", - "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", "requires": { "delayed-stream": "~1.0.0" } @@ -3805,7 +3770,6 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "optional": true, "requires": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" @@ -4531,9 +4495,9 @@ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" }, "fast-json-stable-stringify": { "version": "2.0.0", @@ -4738,12 +4702,12 @@ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" }, "form-data": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", - "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", "requires": { "asynckit": "^0.4.0", - "combined-stream": "1.0.6", + "combined-stream": "^1.0.6", "mime-types": "^2.1.12" } }, @@ -5696,11 +5660,11 @@ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" }, "har-validator": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", - "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", "requires": { - "ajv": "^5.3.0", + "ajv": "^6.5.5", "har-schema": "^2.0.0" } }, @@ -6691,9 +6655,9 @@ "dev": true }, "js-base64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.0.tgz", - "integrity": "sha512-wlEBIZ5LP8usDylWbDNhKPEFVFdI5hCHpnVoT/Ysvoi/PRhJENm/Rlh9TvjYB38HFfKZN7OzEbRjmjvLkFw11g==" + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz", + "integrity": "sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==" }, "js-levenshtein": { "version": "1.1.6", @@ -6726,8 +6690,7 @@ "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "optional": true + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, "jsesc": { "version": "2.5.2", @@ -6745,9 +6708,9 @@ "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" }, "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "json-stringify-safe": { "version": "5.0.1", @@ -7382,22 +7345,12 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" }, - "lodash.assign": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", - "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" - }, "lodash.capitalize": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz", "integrity": "sha1-+CbJtOKoUR2E46yinbBeGk87cqk=", "dev": true }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" - }, "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -7410,11 +7363,6 @@ "integrity": "sha1-hImxyw0p/4gZXM7KRI/21swpXDY=", "dev": true }, - "lodash.mergewith": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz", - "integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ==" - }, "log4js": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", @@ -7886,7 +7834,8 @@ "nan": { "version": "2.12.1", "resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz", - "integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==" + "integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==", + "optional": true }, "nanomatch": { "version": "1.2.13", @@ -7970,19 +7919,6 @@ "which": "1" }, "dependencies": { - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, "semver": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", @@ -8047,9 +7983,9 @@ } }, "node-sass": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.11.0.tgz", - "integrity": "sha512-bHUdHTphgQJZaF1LASx0kAviPH7sGlcyNhWade4eVIpFp6tsn7SV8xNMTbsQFpEV9VXpnwTTnNYlfsZXgGgmkA==", + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.12.0.tgz", + "integrity": "sha512-A1Iv4oN+Iel6EPv77/HddXErL2a+gZ4uBeZUy+a8O35CFYTXhgA8MgLCWBtwpGZdCvTvQ9d+bQxX/QC36GDPpQ==", "requires": { "async-foreach": "^0.1.3", "chalk": "^1.1.1", @@ -8058,12 +7994,10 @@ "get-stdin": "^4.0.1", "glob": "^7.0.3", "in-publish": "^2.0.0", - "lodash.assign": "^4.2.0", - "lodash.clonedeep": "^4.3.2", - "lodash.mergewith": "^4.6.0", + "lodash": "^4.17.11", "meow": "^3.7.0", "mkdirp": "^0.5.1", - "nan": "^2.10.0", + "nan": "^2.13.2", "node-gyp": "^3.8.0", "npmlog": "^4.0.0", "request": "^2.88.0", @@ -8081,18 +8015,15 @@ "which": "^1.2.9" } }, - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + }, + "nan": { + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz", + "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==" } } }, @@ -8664,9 +8595,9 @@ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" }, "psl": { - "version": "1.1.29", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", - "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" + "version": "1.1.31", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", + "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" }, "public-encrypt": { "version": "4.0.3", @@ -9290,21 +9221,6 @@ "lodash": "^4.0.0", "scss-tokenizer": "^0.2.3", "yargs": "^7.0.0" - }, - "dependencies": { - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } } }, "sass-lint": { @@ -10081,9 +9997,9 @@ "dev": true }, "sshpk": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", - "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", "requires": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -10099,8 +10015,7 @@ "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "optional": true + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" } } }, @@ -10149,40 +10064,6 @@ "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", "requires": { "readable-stream": "^2.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "stream-browserify": { @@ -10612,21 +10493,6 @@ "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", "requires": { "glob": "^7.1.2" - }, - "dependencies": { - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } } }, "ts-events": { diff --git a/package.json b/package.json index 697557d4d..58415ae13 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,8 @@ "scripts": { "build": "npm run build:js && npm run build:css", "build:js": "webpack --config webpack.prod.js", - "build:css": "node-sass -o public/css/ --output-style compressed src/sass/", - "build:css:watch": "node-sass -w -r --source-map true --source-map-embed true -o public/css/ --output-style compressed src/sass/", + "build:css": "node-sass -o public/css/ --output-style compressed src/sass/themes", + "build:css:watch": "node-sass -w -r --source-map true --source-map-embed true -o public/css/ --output-style compressed src/sass/themes", "build:tests": "echo -e 'NOTE: Use either \"npm build:unittests\" or \"npm build:uitests\"\n' && exit 1", "build:unittests": "webpack --config webpack.tests.js", "build:uitests": "npm run build:css && webpack --config webpack.tests.js", @@ -67,7 +67,7 @@ "file-saver": "2.0.0", "messageformat": "^2.0.5", "msgpack-lite": "~0.1.26", - "node-sass": "^4.11.0", + "node-sass": "^4.12.0", "sdp": "~2.9.0", "ts-events": "^3.1.5", "ts-loader": "^5.3.3", diff --git a/public/img/ic_dnd_mention_dark.svg b/public/img/ic_dnd_mention_dark.svg new file mode 100644 index 000000000..980545831 --- /dev/null +++ b/public/img/ic_dnd_mention_dark.svg @@ -0,0 +1,35 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/public/img/ic_dnd_total_silence_dark.svg b/public/img/ic_dnd_total_silence_dark.svg new file mode 100644 index 000000000..e79691274 --- /dev/null +++ b/public/img/ic_dnd_total_silence_dark.svg @@ -0,0 +1,62 @@ + + + + + + + image/svg+xml + + + + + + + + + diff --git a/public/img/ic_image_24px_dark.svg b/public/img/ic_image_24px_dark.svg new file mode 100644 index 000000000..51e8391d7 --- /dev/null +++ b/public/img/ic_image_24px_dark.svg @@ -0,0 +1 @@ + diff --git a/public/img/ic_insert_drive_file_24px_dark.svg b/public/img/ic_insert_drive_file_24px_dark.svg new file mode 100644 index 000000000..acc47e766 --- /dev/null +++ b/public/img/ic_insert_drive_file_24px_dark.svg @@ -0,0 +1 @@ + diff --git a/public/img/ic_location_on_24px_dark.svg b/public/img/ic_location_on_24px_dark.svg new file mode 100644 index 000000000..ca28ba29e --- /dev/null +++ b/public/img/ic_location_on_24px_dark.svg @@ -0,0 +1 @@ + diff --git a/public/img/ic_mic_24px_dark.svg b/public/img/ic_mic_24px_dark.svg new file mode 100644 index 000000000..7562d279b --- /dev/null +++ b/public/img/ic_mic_24px_dark.svg @@ -0,0 +1 @@ + diff --git a/public/img/ic_movie_24px_dark.svg b/public/img/ic_movie_24px_dark.svg new file mode 100644 index 000000000..6d66cb875 --- /dev/null +++ b/public/img/ic_movie_24px_dark.svg @@ -0,0 +1 @@ + diff --git a/public/img/ic_notifications_off_dark.svg b/public/img/ic_notifications_off_dark.svg new file mode 100644 index 000000000..cd0296ee8 --- /dev/null +++ b/public/img/ic_notifications_off_dark.svg @@ -0,0 +1 @@ + diff --git a/public/img/ic_pin_dark.svg b/public/img/ic_pin_dark.svg new file mode 100644 index 000000000..ac8bf71f0 --- /dev/null +++ b/public/img/ic_pin_dark.svg @@ -0,0 +1,10 @@ + + + + diff --git a/public/img/ic_poll_24px_dark.svg b/public/img/ic_poll_24px_dark.svg new file mode 100644 index 000000000..3ef3e38da --- /dev/null +++ b/public/img/ic_poll_24px_dark.svg @@ -0,0 +1 @@ + diff --git a/public/img/ic_unpin_dark.svg b/public/img/ic_unpin_dark.svg new file mode 100644 index 000000000..23f8e99fd --- /dev/null +++ b/public/img/ic_unpin_dark.svg @@ -0,0 +1,10 @@ + + + + diff --git a/public/img/spinner_dark.gif b/public/img/spinner_dark.gif new file mode 100644 index 000000000..470c9b4c2 Binary files /dev/null and b/public/img/spinner_dark.gif differ diff --git a/public/img/wallpaper_dark.png b/public/img/wallpaper_dark.png new file mode 100644 index 000000000..670323df0 Binary files /dev/null and b/public/img/wallpaper_dark.png differ diff --git a/src/components/toggle_button.ts b/src/components/toggle_button.ts index a331015f4..38047aae2 100644 --- a/src/components/toggle_button.ts +++ b/src/components/toggle_button.ts @@ -15,6 +15,8 @@ * along with Threema Web. If not, see . */ +import { ThemeService } from '../services/theme'; + /** * A generic toggle button. * @@ -32,11 +34,17 @@ export default { iconEnabled: '@', iconDisabled: '@', }, - controller: function() { + controller: ['ThemeService', function(themeService: ThemeService) { this.getLabel = () => this.flag ? this.labelEnabled : this.labelDisabled; - this.getIcon = () => this.flag ? this.iconEnabled : this.iconDisabled; + // this.getIcon = () => this.flag ? this.iconEnabled : this.iconDisabled; this.action = () => this.flag ? this.onDisable() : this.onEnable(); - }, + + this.getIcon = () => { + const fn = (this.flag ? this.iconEnabled : this.iconDisabled); + return themeService.themedFilename(fn); + }; + + }], template: ` `, diff --git a/src/directives/message_icon.ts b/src/directives/message_icon.ts index 5be0ef70e..b29150cd7 100644 --- a/src/directives/message_icon.ts +++ b/src/directives/message_icon.ts @@ -16,6 +16,7 @@ */ import {hasValue} from '../helpers'; +import { ThemeService } from '../services/theme'; export default [ function() { @@ -36,11 +37,21 @@ export default [ } }, ); + scope.$watch( + () => scope.ctrl.themeService.currentTheme, (newTheme, oldTheme) => { + if (hasValue(newTheme) && newTheme !== oldTheme) { + scope.ctrl.update(); + } + }, + ); }, controllerAs: 'ctrl', - controller: [function() { + controller: ['ThemeService', function(themeService: ThemeService) { + + this.themeService = themeService; + // Return icon depending on message type. - const getIcon = (msgType: threema.MessageType) => { + const getIconFilename = (msgType: threema.MessageType) => { switch (msgType) { case 'image': return 'ic_image_24px.svg'; @@ -62,6 +73,12 @@ export default [ } }; + // Return icon depending on the current theme + const getIcon = (msgType: threema.MessageType) => { + const fn = getIconFilename(msgType); + return ((fn !== null) ? themeService.themedFilename(fn) : null); + }; + this.update = () => { this.icon = getIcon(this.message.type); this.altText = this.message.type + ' icon'; diff --git a/src/directives/message_quote.ts b/src/directives/message_quote.ts index 35b22e43b..0f93c4b03 100644 --- a/src/directives/message_quote.ts +++ b/src/directives/message_quote.ts @@ -31,10 +31,11 @@ export default [ controllerAs: 'ctrl', controller: [function() { this.contact = () => webClientService.contacts.get(this.quote.identity); + this.color = () => ((this.contact().color) === '#181818') ? 'rgb(0, 150, 136)' : (this.contact().color); }], template: ` -
- +
diff --git a/src/partials/dialog.settings.html b/src/partials/dialog.settings.html index c4201365c..823377d87 100644 --- a/src/partials/dialog.settings.html +++ b/src/partials/dialog.settings.html @@ -54,6 +54,25 @@

settings.SETTINGS

+
+ Theme + + + + +

{{ctrl.themeService.getNameForThemeID(themeID)}}

+
+
+
+
diff --git a/src/partials/messenger.conversation.html b/src/partials/messenger.conversation.html index 509542d4e..78d418bf8 100644 --- a/src/partials/messenger.conversation.html +++ b/src/partials/messenger.conversation.html @@ -56,7 +56,7 @@

messenger.PRIVATE_CHAT

  • - ... + ...
  • diff --git a/src/partials/messenger.navigation.html b/src/partials/messenger.navigation.html index 3b870df3d..28a881562 100644 --- a/src/partials/messenger.navigation.html +++ b/src/partials/messenger.navigation.html @@ -89,13 +89,13 @@ - + - + - + {{ conversation.unreadCount }} diff --git a/src/partials/messenger.ts b/src/partials/messenger.ts index 3a6db20f9..fc619e9e4 100644 --- a/src/partials/messenger.ts +++ b/src/partials/messenger.ts @@ -36,6 +36,7 @@ import {NotificationService} from '../services/notification'; import {ReceiverService} from '../services/receiver'; import {SettingsService} from '../services/settings'; import {StateService} from '../services/state'; +import {ThemeService} from '../services/theme'; import {TimeoutService} from '../services/timeout'; import {VersionService} from '../services/version'; import {WebClientService} from '../services/webclient'; @@ -132,12 +133,13 @@ class SendFileController extends DialogController { */ class SettingsController { - public static $inject = ['$mdDialog', '$window', 'SettingsService', 'NotificationService']; + public static $inject = ['$mdDialog', '$window', 'SettingsService', 'NotificationService', 'ThemeService']; public $mdDialog: ng.material.IDialogService; public $window: ng.IWindowService; public settingsService: SettingsService; private notificationService: NotificationService; + private themeService: ThemeService; public activeElement: HTMLElement | null; private desktopNotifications: boolean; @@ -149,7 +151,8 @@ class SettingsController { constructor($mdDialog: ng.material.IDialogService, $window: ng.IWindowService, settingsService: SettingsService, - notificationService: NotificationService) { + notificationService: NotificationService, + themeService: ThemeService) { this.$mdDialog = $mdDialog; this.$window = $window; this.settingsService = settingsService; @@ -160,6 +163,7 @@ class SettingsController { this.notificationPermission = notificationService.getNotificationPermission(); this.notificationPreview = notificationService.getWantsPreview(); this.notificationSound = notificationService.getWantsSound(); + this.themeService = themeService; } public cancel(): void { @@ -190,7 +194,6 @@ class SettingsController { public setWantsSound(notificationSound: boolean) { this.notificationService.setWantsSound(notificationSound); } - } interface ConversationStateParams extends UiStateParams { @@ -218,6 +221,7 @@ class ConversationController { private stateService: StateService; private mimeService: MimeService; private timeoutService: TimeoutService; + private themeService: ThemeService; // Third party services private $mdDialog: ng.material.IDialogService; @@ -274,7 +278,7 @@ class ConversationController { '$mdDialog', '$mdToast', '$translate', '$filter', '$state', '$transitions', 'WebClientService', 'StateService', 'ReceiverService', 'MimeService', 'VersionService', - 'ControllerModelService', 'TimeoutService', + 'ControllerModelService', 'TimeoutService', 'ThemeService', ]; constructor($stateParams: ConversationStateParams, $log: ng.ILogService, @@ -292,7 +296,8 @@ class ConversationController { mimeService: MimeService, versionService: VersionService, controllerModelService: ControllerModelService, - timeoutService: TimeoutService) { + timeoutService: TimeoutService, + themeService: ThemeService) { this.$stateParams = $stateParams; this.$log = $log; this.webClientService = webClientService; @@ -300,6 +305,7 @@ class ConversationController { this.stateService = stateService; this.mimeService = mimeService; this.timeoutService = timeoutService; + this.themeService = themeService; this.$state = $state; this.$scope = $scope; @@ -524,6 +530,10 @@ class ConversationController { .hideDelay(hideDelayMs)); } + public getSpinner(): string { + return this.themeService.themedFilename('img/spinner.gif'); + } + /** * Submit function for input field. Can contain text or file data. * Return whether sending was successful. @@ -935,14 +945,17 @@ class NavigationController { private $translate: ng.translate.ITranslateService; private $state: UiStateService; + public themeService; + public static $inject = [ '$log', '$state', '$mdDialog', '$translate', - 'WebClientService', 'StateService', 'ReceiverService', 'NotificationService', 'TrustedKeyStore', + 'WebClientService', 'StateService', 'ThemeService', 'ReceiverService', 'NotificationService', 'TrustedKeyStore', ]; constructor($log: ng.ILogService, $state: UiStateService, $mdDialog: ng.material.IDialogService, $translate: ng.translate.ITranslateService, webClientService: WebClientService, stateService: StateService, + themeService: ThemeService, receiverService: ReceiverService, notificationService: NotificationService, trustedKeyStoreService: TrustedKeyStoreService) { @@ -961,6 +974,7 @@ class NavigationController { this.$mdDialog = $mdDialog; this.$translate = $translate; this.$state = $state; + this.themeService = themeService; } public contacts(): threema.ContactReceiver[] { diff --git a/src/sass/app.scss b/src/sass/_app.scss similarity index 100% rename from src/sass/app.scss rename to src/sass/_app.scss index cbdbc35c8..bce286f54 100644 --- a/src/sass/app.scss +++ b/src/sass/_app.scss @@ -25,6 +25,7 @@ // Components: Micro layout files. Your styles for buttons and navigation and // similar page components. //@import 'components/lists'; +@import 'components/buttons'; @import 'components/spinner'; @import 'components/links'; @import 'components/scrollbars'; @@ -41,7 +42,6 @@ @import 'components/avatar_editor'; @import 'components/avatar_area'; @import 'components/drag_file'; -@import 'components/buttons'; @import 'components/mediabox'; @import 'components/mention'; @import 'components/backbutton'; diff --git a/src/sass/base/_typography.scss b/src/sass/base/_typography.scss index 05f99310f..119fe9506 100644 --- a/src/sass/base/_typography.scss +++ b/src/sass/base/_typography.scss @@ -21,6 +21,7 @@ textarea { } em { + color: $text-dark-color; font-style: italic; } diff --git a/src/sass/components/_avatar_area.scss b/src/sass/components/_avatar_area.scss index ea95351b9..e0d59ca8b 100644 --- a/src/sass/components/_avatar_area.scss +++ b/src/sass/components/_avatar_area.scss @@ -8,7 +8,7 @@ position: relative; margin: auto; border-radius: 50%; - background-color: rgb(198, 198, 198); + background-color: $avatar-background-color; width: $avatar-area-size; height: $avatar-area-size; overflow: hidden; diff --git a/src/sass/components/_backbutton.scss b/src/sass/components/_backbutton.scss index d188c9c1d..f9cc62e2b 100644 --- a/src/sass/components/_backbutton.scss +++ b/src/sass/components/_backbutton.scss @@ -7,7 +7,7 @@ md-icon { transform: scale(1.2); - color: $material-grey-dark; + color: $icon-dark-color; } &.md-focused { diff --git a/src/sass/components/_battery.scss b/src/sass/components/_battery.scss index 36d90b152..d1091953e 100644 --- a/src/sass/components/_battery.scss +++ b/src/sass/components/_battery.scss @@ -4,7 +4,7 @@ right: 24px; &.alert md-icon { - color: $status-error; + color: $status-error-color; } md-icon { diff --git a/src/sass/components/_buttons.scss b/src/sass/components/_buttons.scss index cfa11bf30..4b321975b 100644 --- a/src/sass/components/_buttons.scss +++ b/src/sass/components/_buttons.scss @@ -1,6 +1,151 @@ +md-dialog md-dialog-actions .md-button { + background-color: $button-color-enabled; + color: $button-text-dark-color !important; // $button-text-dark-color +} + +md-select { + .md-select-value { + color: $text-medium-color !important; + + .md-select-placeholder { + color: $text-medium-color; + } + + .md-select-icon { + color: $text-medium-color; + } + } +} + +.md-select-menu-container { + .md-active { + md-select-menu>* { + background-color: $background-dark-color; + color: $text-medium-color; + } + } +} + +md-select-menu { + md-content { + background-color: $background-light-color !important; + + md-option { + background-color: $background-light-color !important; + color: $text-medium-color; + + &:not([disabled]) { + &:hover { + background-color: $button-hover-color !important; + color: $text-medium-color; + } + } + + &[selected] { + background-color: $button-selected-color !important; + color: $text-medium-color !important; + } + } + } +} + +md-menu-content md-menu-item { + background-color: $background-light-color; + color: $button-text-dark-color; +} + + button { i.material-icons { margin-bottom: 3px; vertical-align: middle; + color: $icon-dark-color !important; + } +} + +.md-button { + .md-fab { + background-color: $primary-500; + color: $button-text-dark-color; // $button-text-dark-color + + md-icon { + color: $button-text-dark-color; + } + + :not([disabled]) { + :hover { + background-color: $primary-500; + } + + .md-focused { + background-color: $primary-500; + } + } + } + + .md-primary { + background-color: $primary-500; + color: $button-text-dark-color; // $button-text-dark-color + } + + .md-raised { + background-color: $button-color-enabled; + color: $button-text-dark-color; + + :not([disabled]) md-icon { + color: $button-text-dark-color; + } + + :not([disabled]) { + :hover { + background-color: $button-color-enabled; + } + + .md-focused { + background-color: $button-color-pressed; + } + } + } + + .md-warn { + color: $status-error-color; + + :not([disabled]) md-icon { + color: $status-error-color; + } + + .md-raised { + background-color: $status-error-color; + color: $button-text-light-color; + + :not([disabled]) md-icon { + color: $button-text-light-color; + + :hover { + background-color: $status-error-disabled-color; + } + + .md-focused { + background-color: $status-error-disabled-color; + } + } + } + + md-fab { + background-color: $status-error-color; + color: $button-text-light-color; + + :not([disabled]) md-icon { + color: $button-text-light-color; + + :hover { + background-color: $status-error-disabled-color; + } + + .md-focused { + background-color: $status-error-disabled-color; + } + } + } } } diff --git a/src/sass/components/_dialogs.scss b/src/sass/components/_dialogs.scss index 538feda7d..b69629e98 100644 --- a/src/sass/components/_dialogs.scss +++ b/src/sass/components/_dialogs.scss @@ -27,6 +27,7 @@ md-dialog { md-dialog-content { line-height: 1.3em; + color: $text-dark-color; // If a h2 is the first child of a dialog, remove the top margin .md-dialog-content > h2 { @@ -76,3 +77,52 @@ md-dialog.message-history-dialog { } } } + +// sass-lint:disable no-vendor-prefixes +// sass-lint:disable force-pseudo-nesting +// sass-lint:disable no-mergeable-selectors +md-input-container { + .md-input::-webkit-input-placeholder { + color: darken($text-placeholder-color, 30%); + } + + .md-input:-moz-placeholder { + color: darken($text-placeholder-color, 30%); + } + + .md-input::-moz-placeholder { + color: darken($text-placeholder-color, 30%); + } + + // TODO: Investigate this. + // If this pseudo-class is nested within its parent + // it doesn't work in Chrome. I have no clue why. + .md-input:-ms-input-placeholder { + color: darken($text-placeholder-color, 30%); + } + + .md-input::-webkit-input-placeholder { + color: darken($text-placeholder-color, 30%); + } +} + +md-input-container.md-input-focused { + .md-input::-webkit-input-placeholder { + color: darken($text-placeholder-color, 20%); + } + + .md-input:-moz-placeholder { + color: darken($text-placeholder-color, 20%); + } + + .md-input:-ms-input-placeholder { + color: darken($text-placeholder-color, 20%); + } + + .md-input::-webkit-input-placeholder { + color: darken($text-placeholder-color, 20%); + } +} +// sass-lint:enable no-vendor-prefixes +// sass-lint:enable force-pseudo-nesting +// sass-lint:enable no-mergeable-selectors diff --git a/src/sass/components/_emoji_picker.scss b/src/sass/components/_emoji_picker.scss index 7382c4d04..47120cd21 100644 --- a/src/sass/components/_emoji_picker.scss +++ b/src/sass/components/_emoji_picker.scss @@ -1,11 +1,11 @@ .twemoji-picker { margin: 0; - background-color: $background-grey; + background-color: $background-emoji-picker-color; padding: 0 8px; min-height: 216px; &.outline { - border: 2px solid #dbdbdb; + border: 2px solid $border-light-color; border-radius: 4px; width: 366px; } @@ -27,8 +27,8 @@ position: relative; left: 1px; margin-left: -1px; - border: 1px solid $background-grey; - background: $background-grey; + border: 1px solid $background-emoji-picker-color; + background: $background-emoji-picker-color; cursor: pointer; padding: 4px; height: 32px; @@ -46,13 +46,13 @@ right: 0; bottom: 0; left: 0; - border: 1px solid #ffffff; - background: #ffffff; + border: 1px solid $background-light-color; + background: $background-light-color; padding: 10px 10px 0; overflow-y: scroll; &::selection { - background: rgba(255, 255, 255, 0); + background: $white-zero; } } @@ -61,8 +61,8 @@ &:checked ~ label { z-index: 2; - border-bottom: 1px solid #ffffff; - background: #ffffff; + border-bottom: 1px solid $background-light-color; + background: $background-light-color; } &:checked ~ label ~ .content { diff --git a/src/sass/components/_placeholder.scss b/src/sass/components/_placeholder.scss index acdfdd778..248c92e71 100644 --- a/src/sass/components/_placeholder.scss +++ b/src/sass/components/_placeholder.scss @@ -5,7 +5,7 @@ &:not(:focus) { &::before { cursor: text; - color: $material-grey; + // color: $material-grey-color; content: attr(data-placeholder); } } diff --git a/src/sass/components/_scrollbars.scss b/src/sass/components/_scrollbars.scss index a8e74494c..7d8c4ab79 100644 --- a/src/sass/components/_scrollbars.scss +++ b/src/sass/components/_scrollbars.scss @@ -1,13 +1,13 @@ // Webkit specific global styling // sass-lint:disable no-vendor-prefixes ::-webkit-scrollbar { - border: 1px solid #f9f9f9; - background-color: $scrollbar-color-bg; + border: 1px solid $border-light-color; + background-color: $scrollbar-background-color; width: 6px; } ::-webkit-scrollbar-thumb { - background-color: $scrollbar-color-thumb; + background-color: $scrollbar-thumb-color; } // sass-lint:enable no-vendor-prefixes @@ -16,6 +16,6 @@ // Note: Linter doesn't recognise 'scrollbar-*' properties, yet. // sass-lint:disable no-misspelled-properties scrollbar-width: thin; // Unfortunately Firefox does not support exact pixel values - scrollbar-color: $scrollbar-color-thumb $scrollbar-color-bg; + scrollbar-color: $scrollbar-thumb-color $scrollbar-background-color; // sass-lint:enable no-misspelled-properties } diff --git a/src/sass/components/_spinner.scss b/src/sass/components/_spinner.scss index e6e6dd869..13449cfe0 100644 --- a/src/sass/components/_spinner.scss +++ b/src/sass/components/_spinner.scss @@ -16,15 +16,13 @@ } } -@mixin loading-spinner( - $diameter, +@mixin loading-spinner($diameter, $thickness: 5px, - $color-fg: $material-grey-dark, - $color-bg: rgba(0, 0, 0, .1) -) { + $color-fg: $material-grey-dark-color, + $color-bg: rgba(0, 0, 0, .1)) { display: block; - > :first-child { + &>:first-child { display: block; animation: rotater 1.1s infinite linear; border: $thickness solid $color-bg; diff --git a/src/sass/components/_verification_level.scss b/src/sass/components/_verification_level.scss index 713e6c45b..e60ec252e 100644 --- a/src/sass/components/_verification_level.scss +++ b/src/sass/components/_verification_level.scss @@ -1,5 +1,7 @@ -// Verification level +// Verification level. + .verification-dots { + div { display: inline-block; margin-right: 2px; @@ -7,12 +9,12 @@ background-color: #e0e0e0; width: 11px; height: 11px; - } + } &.level1 { div { &:nth-of-type(1) { - background-color: $status-error; + background-color: $status-error-color; } } } @@ -21,7 +23,7 @@ div { &:nth-of-type(1), &:nth-of-type(2) { - background-color: $status-warning; + background-color: $status-warning-color; } } @@ -29,7 +31,7 @@ div { &:nth-of-type(1), &:nth-of-type(2) { - background-color: $work-blue; + background-color: $work-blue-color; } } } @@ -37,7 +39,7 @@ &.level3 { div { - background-color: $status-ok; + background-color: $status-ok-color; } &.work { @@ -45,7 +47,7 @@ &:nth-of-type(1), &:nth-of-type(2), &:nth-of-type(3) { - background-color: $work-blue; + background-color: $work-blue-color; } } } diff --git a/src/sass/helpers/_colors.scss b/src/sass/helpers/_colors.scss index 0dc925aea..e322e9b63 100644 --- a/src/sass/helpers/_colors.scss +++ b/src/sass/helpers/_colors.scss @@ -2,8 +2,8 @@ $status-ok: #4caf50; $status-warning: #ff9800; $status-error: #f44336; $status-starred: #ffc107; -$border-grey: #dddddd; -$background-grey: lighten($border-grey, 7%); +// $border-dark-color: #dddddd; +$background-grey: lighten($border-dark-color, 7%); $material-grey: rgba(0, 0, 0, .54); $material-grey-dark: rgba(0, 0, 0, .87); $url-light-blue: #63a6cf; @@ -17,7 +17,7 @@ $scrollbar-color-thumb: #cccccc; $material-card-shadow: 0 2px 5px 0 rgba(0, 0, 0, .16), 0 2px 5px 0 rgba(0, 0, 0, .23); -$active-placeholder-color: #d3d3d3; +// $active-placeholder-color: #d3d3d3; .color-status-ok { color: $status-ok; @@ -31,5 +31,5 @@ $active-placeholder-color: #d3d3d3; color: $status-error; } -.material-icons.md-medium-dark { color: rgba(0, 0, 0, .54); } -.material-icons.md-medium-dark.md-inactive { color: rgba(0, 0, 0, .26); } +// .material-icons.md-medium-dark { color: rgba(0, 0, 0, .54); } +// .material-icons.md-medium-dark.md-inactive { color: rgba(0, 0, 0, .26); } diff --git a/src/sass/helpers/_message_bubble.scss b/src/sass/helpers/_message_bubble.scss index 8b9b6c786..59bd1b69b 100644 --- a/src/sass/helpers/_message_bubble.scss +++ b/src/sass/helpers/_message_bubble.scss @@ -1,5 +1,3 @@ -$message-bubble-color-in: #f7f7f7; -$message-bubble-color-out: #dff0d8; $bubble-triangle-size: $main-padding; @mixin message-bubble-shadow { diff --git a/src/sass/layout/_main.scss b/src/sass/layout/_main.scss index e4a1419f8..577ea2b31 100644 --- a/src/sass/layout/_main.scss +++ b/src/sass/layout/_main.scss @@ -29,9 +29,8 @@ // Set min height of messenger &.wide #main { min-height: 272px; - } + } // Set min height of welcome screen - // Set min height of welcome screen &:not(.wide) #main { height: auto; min-height: 620px; @@ -40,7 +39,7 @@ #main { border-radius: $material-radius; - box-shadow: $material-card-shadow; + box-shadow: $material-card-shadow-color; width: 100%; height: 100%; overflow: hidden; @@ -67,9 +66,10 @@ height: 100%; > div.ng-scope { - background-color: #efebe9; + background-color: $background-dark-color; height: 100%; + // Default style for the header in the detail .detail-header { display: flex; @@ -77,13 +77,14 @@ align-items: center; z-index: 18; box-shadow: 1px 2px 4px -2px rgba(0, 0, 0, .2); - background-color: $dark-background-color; + background-color: $conversation-header-color; padding: 0 $main-padding; min-height: 68px; - > * { + >* { margin-left: 8px; - } + color: $text-medium-color; + } // TODO This might need renaming to header-detail .header-detail { display: flex; @@ -113,10 +114,16 @@ md-progress-circular { display: inline-block; } + + .material-icons { + color: $icon-dark-color; + } } } .detail-content { + background-color: $background-dark-color; + color: $text-medium-color; ul { margin: 0; @@ -130,8 +137,18 @@ } } + md-card md-card-content { + background-color: $background-light-color; + color: $text-medium-color; + } + + md-card-title { + background-color: $background-light-color; + color: $text-medium-color; + } + // editable or readonly detail content - > .form { + >.form { display: flex; flex-direction: column; height: 100%; @@ -142,6 +159,8 @@ overflow: hidden; eee-avatar { + background-color: $background-light-color; + img { position: relative; top: calc(-100%); @@ -177,6 +196,7 @@ // be sure the avatar has always the same height as width &.avatar { position: relative; + background-color: $background-light-color; width: 50%; overflow: hidden; @@ -195,7 +215,6 @@ border-radius: 0; width: 100%; height: auto; - } } } @@ -228,7 +247,7 @@ &.show-detail { #navigation { flex: 1 6 30%; - border-right: 1px solid #dddddd; + border-right: 1px solid $border-dark-color; min-width: 200px; max-width: 30%; } @@ -238,27 +257,64 @@ max-width: 70%; } } - } .material-icons { + color: $icon-material-grey-color; + &.as-button { opacity: .5; cursor: pointer; + color: $icon-material-grey-color; &:hover { opacity: 1; } } + .md-dark { + color: $icon-dark-color; + } + + .md-light { + color: $icon-light-color; + } + + .md-primary { + color: $icon-material-grey-color; + } +} + +md-dialog.md-default-theme, +md-dialog { + background-color: $background-medium-color; } .md-dialog-content { + background-color: $background-medium-color; + color: $text-medium-color; + &.center { text-align: center; } } +md-checkbox { + .md-default-theme { + :note(.md-checked) { + .md-icon { + border-color: $text-medium-color; + } + } + } + + :not(.md-checked) { + .md-icon { + border-color: $text-medium-color; + } + } +} + input.threema-id { text-transform: uppercase; } @@ -300,7 +356,7 @@ a.click-action { .key-values { dt { padding-bottom: ($main-padding); - color: rgb(0, 150, 136); + color: $primary-500; } dd { @@ -331,16 +387,41 @@ a.click-action { } } +md-input-container { -// angular material extensions -md-toast.md-center { - left: 50%; - transform: translate3d(-50%, 0, 0); + .md-input { + border-color: $text-dark-color; + color: $text-dark-color; + } + + label { + color: $text-medium-color; + } + + .md-input-has-value label { + color: $text-medium-color; + } + + :not(.md-input-invalid).md-input-focused { + border-color: $text-dark-color; + } + + :not(.md-input-invalid).md-input-focused label { + color: $text-dark-color; + } } -md-toast .md-toast-content { - span { - text-align: center; +// angular material extensions +md-toast { + .md-center { + left: 50%; + transform: translate3d(-50%, 0, 0); + } + + .md-toast-content { + span { + text-align: center; + } } } @@ -348,7 +429,7 @@ md-toast .md-toast-content { background-color: transparent; } -md-list-item .md-list-item-inner > md-checkbox .md-label { +md-list-item .md-list-item-inner>md-checkbox .md-label { display: inline-block; white-space: inherit; } @@ -375,3 +456,20 @@ md-list-item .md-list-item-inner > md-checkbox .md-label { font-size: .8em; font-weight: 300; } + +md-toolbar { + :not(.md-menu-toolbar) { + background-color: $md-toolbar-color; + color: $md-toolbar-text-color; + + .md-button { + .md-icon-button md-icon { + color: $md-toolbar-button-color; + } + } + } +} + +md-menu-content { + background-color: $background-light-color; +} diff --git a/src/sass/sections/_compose_area.scss b/src/sass/sections/_compose_area.scss index 140f7baa6..286cf751e 100644 --- a/src/sass/sections/_compose_area.scss +++ b/src/sass/sections/_compose_area.scss @@ -1,6 +1,7 @@ compose-area { > div { box-shadow: 0 -2px 4px -2px rgba(0, 0, 0, .2); + color: $text-dark-color; &:first-child { display: flex; @@ -18,9 +19,9 @@ compose-area { &:nth-of-type(2) { flex-grow: 1; - border: 1px solid $border-grey; + border: 1px solid $border-dark-color; border-radius: $material-radius; - background-color: $light-background-color; + background-color: $background-medium-color; overflow-x: hidden; overflow-y: auto; @@ -86,7 +87,7 @@ compose-area { // On dragover &.is-dragover div.compose { - border: 4px dashed #d3d3d3; + border: 4px dashed $background-dark-color; text-align: center; line-height: $footer-height - 20px; font-size: 1.4em; diff --git a/src/sass/sections/_conversation.scss b/src/sass/sections/_conversation.scss index f8b72c5fb..10622f361 100644 --- a/src/sass/sections/_conversation.scss +++ b/src/sass/sections/_conversation.scss @@ -2,11 +2,14 @@ display: flex; position: relative; flex-direction: column; - background-image: url('../img/wallpaper_light.png?'); + background-image: url($wallpaper); height: 100%; .detail-header { + background-color: $conversation-header-color; + color: $button-text-dark-color; + .header-avatar { cursor: pointer; } @@ -25,9 +28,19 @@ margin: 0 0 4px; padding: 0; font-size: 120%; + + } + + .conversation-header-details-detail { + display: inherit; + max-width: 100%; + overflow: hidden; + text-overflow: ellipsis; + line-height: 1.3; + white-space: nowrap; + color: $text-dark-color; } - .conversation-header-details-detail, .conversation-header-details-name { display: inherit; max-width: 100%; @@ -35,6 +48,7 @@ text-overflow: ellipsis; line-height: 1.3; white-space: nowrap; + color: $conversation-header-text-color; } } @@ -57,7 +71,7 @@ flex-direction: row; align-items: center; justify-content: space-between; - background-color: #ffffff; + background-color: $background-medium-color; padding: 8px; .message-quote { @@ -87,12 +101,17 @@ } #conversation-footer { - background-color: $dark-background-color; + background-color: $background-dark-color; .chat-input { margin: 0; padding: 0; width: 100%; + + .compose { + color: $text-dark-color; + caret-color: $text-medium-color; + } } #mention-selector { @@ -104,14 +123,15 @@ list-style-type: none; > li { + cursor: pointer; &:not(:hover) { - &:not(.selected) { - background-color: #ffffff; + :not(.selected) { + background-color: $background-medium-color; } } - } + } } .contact-badge { @@ -147,13 +167,15 @@ // Quoting .message-quote-content { - border-left: 5px solid #0000ff; + border-left: 5px solid $message-quote-color; padding-left: 5px; + color: $text-dark-color; font-size: .9em; .message-name { display: block; margin-bottom: 8px; + color: $message-quote-color; font-size: .9em; font-weight: bold; } @@ -183,7 +205,7 @@ @include message-bubble-shadow; display: inline-block; border-radius: 50%; - background-color: #ffffff; + background-color: $spinner-background-color; padding: 6px; width: 30px; height: 30px; @@ -193,6 +215,7 @@ &.typing-indicator { .message-body { min-width: 15px; + color: $text-dark-color; } } } @@ -257,6 +280,7 @@ padding: 8px; min-width: 64px; max-width: 85%; + color: $text-dark-color; &:not(.text-message-body) { // set fixed height to thumbnails @@ -308,6 +332,7 @@ span { white-space: pre-wrap; + color: $text-dark-color; } } @@ -353,7 +378,7 @@ align-items: flex-end; margin-top: 4px; height: 16px; - color: #808080; + color: $text-dark-color; font-size: .8em; .message-state { @@ -362,10 +387,19 @@ i { position: relative; top: 2px; + color: $text-dark-color; + } + + i.user-ack { + color: #4caf50; + } + + i.user-dec { + color: #ff9800; } i.timeout { - color: $status-error; + color: $status-error-color; } } @@ -375,6 +409,7 @@ height: 1em; min-height: 1em; vertical-align: top; + color: $text-dark-color; font-size: 1em; } } @@ -384,6 +419,7 @@ .message-body { position: relative; background-color: $message-bubble-color-in; + color: $text-dark-color; } // arrow @@ -410,6 +446,7 @@ .message-body { position: relative; background-color: $message-bubble-color-out; + color: $text-dark-color; } // arrow @@ -441,7 +478,7 @@ justify-content: center; .message-body { - background-color: #fcf8e3; + background-color: $ctrl-message-bubble-color; .message-text { margin-top: 0; @@ -460,7 +497,7 @@ .line { flex-grow: 1; - border-bottom: 1px solid #bbbbbb; + border-bottom: 1px solid $text-dark-color; text-align: center; line-height: 0; } @@ -468,7 +505,8 @@ .text { margin: 0; padding: 0 10px; - text-shadow: 0 0 4px #bbbbbb; + text-shadow: 0 0 4px $text-dark-color; + color: $text-dark-color; font-size: .9em; font-weight: 300; } @@ -489,6 +527,6 @@ md-menu-item { a span { - color: $material-grey-dark; + color: $material-grey-dark-color; } } diff --git a/src/sass/sections/_navigation.scss b/src/sass/sections/_navigation.scss index c4e135dbf..1e13020d6 100644 --- a/src/sass/sections/_navigation.scss +++ b/src/sass/sections/_navigation.scss @@ -1,6 +1,6 @@ // Separator for navigation items @mixin nav-item-separator { - border-bottom: 1px solid $border-grey; + border-bottom: 1px solid $border-dark-color; } #navigation-topheader { @@ -10,10 +10,14 @@ justify-content: center; z-index: 21; box-shadow: -2px 2px 4px -2px rgba(0, 0, 0, .8); - background-color: #424242; + background-color: $navigation-header-color; padding: 0 $main-padding 0 (2 * $main-padding); min-height: 68px; - color: #ffffff; + color: $secondary-000; + + .material-icons.md-light { + color: $icon-light-color !important; + } .my-identity { flex-grow: 1; @@ -37,7 +41,11 @@ #navigation-header { z-index: 18; box-shadow: -2px 2px 4px -2px rgba(0, 0, 0, .4); - background-color: #f5f5f5; + background-color: $background-medium-color; + + .material-icons.md-dark { + color: $icon-dark-color; + } .main { display: flex; @@ -57,24 +65,28 @@ } .search { + $duration-opacity: .1s; $duration-height: .2s; + + // Animation when disappearing transition: opacity $duration-opacity linear, max-height $duration-height ease-out $duration-opacity, visibility 0s linear $duration-height; + visibility: hidden; opacity: 0; - // Animation when disappearing max-height: 0; input { &[type='text'] { margin: 0; - border: 1px solid #dddddd; + border: 1px solid $text-medium-color; border-radius: $material-radius; - background-color: #ffffff; + background-color: $background-light-color; padding: $main-padding; width: 100%; + color: $text-dark-color; box-sizing: border-box; .md-errors-spacer { @@ -100,11 +112,12 @@ #navigation-conversations, #navigation-contacts { @include scrollbar; + background-color: $navigation-background-color; .empty { margin-top: 1em; margin-left: 16px; - color: $material-grey; + color: $text-dark-color; font-size: 1.2em; font-weight: 300; } @@ -114,7 +127,6 @@ $border-width: 4px; $border-count: 2; flex: 1; - background-color: #ffffff; overflow-y: auto; .loading-element { @@ -124,23 +136,28 @@ .conversation-wrapper { @include nav-item-separator; display: block; + background-color: $navigation-background-color; .conversation { display: flex; flex-direction: row; align-items: center; - border-left: $border-width * $border-count solid #ffffff; + border-left: $border-width * $border-count solid $navigation-background-color; padding: (1.5 * $main-padding) $main-padding - ($border-width * ($border-count - 1)); - &.active, - &:hover { - border-color: $dark-background-color; - background-color: $dark-background-color; + &.active { + border-color: $navigation-background-highlight-color; + background-color: $navigation-background-highlight-color; + &:hover { + border-color: $navigation-background-highlight-color; + background-color: $navigation-background-highlight-color; + } } &:hover { &:not(.active) { - cursor: pointer; + border-color: $navigation-background-highlight-color; + background-color: $navigation-background-highlight-color; } } @@ -150,8 +167,8 @@ to right, $status-error, $status-error 50%, - #ffffff 50%, - #ffffff 100% + $navigation-background-color 50%, + $navigation-background-color 100% ) 1 100%; &.active { @@ -159,8 +176,18 @@ to right, $status-error, $status-error 50%, - $dark-background-color 50%, - $dark-background-color 100% + $navigation-background-highlight-color 50%, + $navigation-background-highlight-color 100% + ) 1 100%; + } + + &:hover { + border-image: linear-gradient( + to right, + $status-error, + $status-error 50%, + $navigation-background-highlight-color 50%, + $navigation-background-highlight-color 100% ) 1 100%; } } @@ -171,8 +198,8 @@ to right, $status-starred, $status-starred 50%, - #ffffff 50%, - #ffffff 100% + $navigation-background-color 50%, + $navigation-background-color 100% ) 1 100%; &.active { @@ -180,8 +207,18 @@ to right, $status-starred, $status-starred 50%, - $dark-background-color 50%, - $dark-background-color 100% + $navigation-background-highlight-color 50%, + $navigation-background-highlight-color 100% + ) 1 100%; + } + + &:hover { + border-image: linear-gradient( + to right, + $status-starred, + $status-starred 50%, + $navigation-background-highlight-color 50%, + $navigation-background-highlight-color 100% ) 1 100%; } } @@ -224,7 +261,7 @@ flex-direction: row; flex-grow: 1; justify-content: space-between; - color: #000000; + color: $text-medium-color; font-weight: bold; .title { @@ -254,7 +291,7 @@ flex-direction: row; align-items: center; justify-content: space-between; - color: $material-grey; + color: $latest-message-text-color; .left { display: flex; @@ -274,12 +311,11 @@ } } - .message-name, - .message-text { - line-height: 1.7em; - } - .message-name { + .message-text { + line-height: 1.7em; + } + &::after { margin-right: 4px; content: ':'; @@ -327,6 +363,10 @@ display: none; } } + + .message-date { + color: $latest-message-text-color; + } } } } @@ -336,7 +376,7 @@ border-radius: 5px; background-color: $status-error; padding: 0 5px; - color: #ffffff; + color: $secondary-000; font-size: .9em; } } @@ -345,19 +385,22 @@ #navigation-contacts { flex: 1; + background-color: $navigation-background-color; overflow-y: scroll; .contact { @include nav-item-separator; + display: flex; flex-direction: row; align-items: center; justify-content: flex-start; - border-left: 4px solid #ffffff; + border-left: 4px solid $background-light-color; padding: 12px 8px; .avatar-box { padding-right: 8px; + color: $text-medium-color; } .left { @@ -373,16 +416,31 @@ } .name { + color: $text-medium-color; font-weight: bold; } + .identity { + color: $text-medium-color; + } + .nickname { + color: $text-medium-color; font-size: .8em; } &:hover { - background-color: #f5f5f5; + background-color: $background-dark-color; cursor: pointer; + + &.active { + border-color: $navigation-background-highlight-color; + background-color: $navigation-background-highlight-color; + } + + &:not(.active) { + background-color: $navigation-background-highlight-color; + } } } @@ -399,7 +457,7 @@ position: relative; md-icon { - color: #ffffff; + color: $button-text-light-color; } .fab-button-add-contact { diff --git a/src/sass/sections/_noscript.scss b/src/sass/sections/_noscript.scss index 5bb6e70ca..c6d27984c 100644 --- a/src/sass/sections/_noscript.scss +++ b/src/sass/sections/_noscript.scss @@ -2,7 +2,7 @@ noscript { div { display: block; margin: 16px auto 0; - background-color: #ffffff; + background-color: $background-medium-color; padding: 16px; width: 50%; text-align: center; diff --git a/src/sass/sections/_status_bar.scss b/src/sass/sections/_status_bar.scss index 6b71d3dc6..6d93edb0e 100644 --- a/src/sass/sections/_status_bar.scss +++ b/src/sass/sections/_status_bar.scss @@ -51,31 +51,31 @@ body { .status-ok { #status-bar { - background-color: $status-ok; + background-color: $status-ok-color; } #title .dot { - fill: $status-ok; + fill: $status-ok-color; } } .status-warning { #status-bar { - background-color: $status-warning; + background-color: $status-warning-color; } #title .dot { - fill: $status-warning; + fill: $status-warning-color; } } .status-error { #status-bar { - background-color: $status-error; + background-color: $status-error-color; } #title .dot { - fill: $status-error; + fill: $status-error-color; } } @@ -83,7 +83,7 @@ body { // the relayed data task (because connection loss on iOS is expected). .status-task-relayed-data { &.status-warning #status-bar { - background-color: $status-ok; + background-color: $status-ok-color; } } diff --git a/src/sass/sections/_welcome.scss b/src/sass/sections/_welcome.scss index 054617394..d9027486a 100644 --- a/src/sass/sections/_welcome.scss +++ b/src/sass/sections/_welcome.scss @@ -1,4 +1,5 @@ #welcome { + background-color: $secondary-000; padding: 16px 32px; line-height: 1.4em; @@ -6,7 +7,7 @@ margin-top: 1em; &.error { - color: $status-error; + color: $status-error-color; } } @@ -18,6 +19,7 @@ &, input { text-align: center; + color: $secondary-999; } md-input-container { diff --git a/src/sass/themes/app-dark.scss b/src/sass/themes/app-dark.scss new file mode 100644 index 000000000..0451b2411 --- /dev/null +++ b/src/sass/themes/app-dark.scss @@ -0,0 +1,147 @@ +$wallpaper: '../../public/img/wallpaper_dark.png?'; // TODO: Use a darker wallpaper + +// Define colors +$threema-green-color: rgb(0, 150, 136); +$dark-gray: rgb(83, 83, 83); +$middle-gray: rgb(112, 112, 112); +$light-gray: rgb(235, 235, 235); + +// Primary +$primary-900: #004d3f; +$primary-800: #00695b; +$primary-700: #00796a; +$primary-600: #00897a; +$primary-500: $threema-green-color; // Standard +$primary-400: #26a699; +$primary-300: #4db6ab; +$primary-200: #80cbc3; +$primary-100: #b2dfdb; +$primary-050: #e0f2f1; +$primary: $primary-500; + +// Secondary +$secondary-999: rgba(0, 0, 0, 1); +$secondary-900: rgba(32, 32, 32, 1); +$secondary-850: rgba(48, 48, 48, 1); +$secondary-800: rgba(65, 65, 65, 1); +$secondary-750: rgba(76, 76, 76, 1); +$secondary-700: rgba(96, 96, 96, 1); +$secondary-600: rgba(116, 116, 116, 1); +$secondary-570: rgba(148, 148, 148, 1); +$secondary-500: rgba(157, 157, 157, 1); // Standard +$secondary-400: rgba(188, 188, 188, 1); +$secondary-320: rgba(219, 219, 219, 1); +$secondary-300: rgba(223, 223, 223, 1); +$secondary-200: rgba(237, 237, 237, 1); +$secondary-100: rgba(245, 245, 245, 1); +$secondary-050: rgba(250, 250, 250, 1); +$secondary-000: rgba(255, 255, 255, 1); +$secondary: $secondary-500; + +// Terniary + +// Material colors +$material-grey-color: $secondary-900; +$material-grey-inactive-color: lighter($material-grey-color, 50%); +$material-grey-dark-color: darken($secondary-900, 25%); +$material-card-shadow-color: px 2px 5px px $material-grey-dark-color, +px 2px 5px px $material-grey-dark-color; + +// Status colors +$status-ok-color: #4caf50; +$status-warning-color: #ff9800; +$status-error-color: #f44336; +$status-error-disabled-color: #f44336; +$status-starred-color: #ffc107; + +// Border colors +$border-dark-color: $secondary-750; +$border-light-color: $secondary-320; + +// Scrollbar colors +$scrollbar-thumb-color: $secondary-800; +$scrollbar-background-color: $secondary-600; + +// Background colors +$background-dark-color: $secondary-900; +$background-medium-color: $secondary-850; +$background-light-color: $secondary-750; + +$background-emoji-picker-color: $background-medium-color; +$navigation-background-color: $background-medium-color; +$navigation-background-highlight-color: $background-dark-color; +$spinner-background-color: $background-medium-color; + +$avatar-background-color: $primary-900; + +// Header colors +$navigation-header-color: $secondary-800; +$conversation-header-color: $secondary-800; + +// Text colors +$text-dark-color: $secondary-500; +$text-medium-color: $secondary-300; +$text-light-color: $secondary-050; + +$conversation-header-text-color: $secondary-050; + +$latest-message-text-color: $secondary-500; +$text-placeholder-color: $secondary-500; +$text-protocol-updated-color: #9dd0f2; + +// md-toolbar colors +$md-toolbar-color: $background-dark-color; +$md-toolbar-text-color: $secondary-800; +$md-toolbar-button-color: $secondary-800; + +// Icon colors +$icon-color: $secondary-000; +$icon-dark-color: $secondary-400; +$icon-light-color: $secondary-400; +$icon-material-grey-color: $secondary-500; + +// Message bubble colors +$message-quote-color: $threema-green-color; +$message-bubble-color-in: rgb(31, 25, 25); +$message-bubble-color-out: rgb(27, 39, 52); +$ctrl-message-bubble-color: #0c2298; //TODO: Check what this color is in the Android App + +// Button colors +$button-color: $material-grey-color; +$button-color-enabled: $secondary-600; +$button-color-disabled: lighten($secondary-700, 65%); +$button-color-pressed: $secondary-750; +$button-hover-color: lighten($background-light-color, 15%); +$button-selected-color: darken($background-light-color, 10%); + +$button-text-dark-color: $secondary-000; +$button-text-light-color: $secondary-900; + +// Misc colors +$active-placeholder-color: $text-dark-color; +$url-light-blue-color: #63a6cf; +$work-blue-color: #3b84df; +$white-zero: rgba(255, 255, 255, 0); + + +.color-status-ok { + color: $status-ok-color; +} + +.color-status-warning { + color: $status-warning-color; +} + +.color-status-error { + color: $status-error-color; +} + +.material-icons.md-medium-dark { + color: $secondary-400; +} + +.material-icons.md-medium-dark.md-inactive { + color: $material-grey-inactive-color; +} + +@import '../app'; diff --git a/src/sass/themes/app-light.scss b/src/sass/themes/app-light.scss new file mode 100644 index 000000000..93562e8b9 --- /dev/null +++ b/src/sass/themes/app-light.scss @@ -0,0 +1,145 @@ +$wallpaper: '../../public/img/wallpaper_light.png?'; + +// Define colors +$threema-green-color: rgb(0, 150, 136); +$dark-gray: rgb(83, 83, 83); +$middle-gray: rgb(112, 112, 112); +$light-gray: rgb(235, 235, 235); + +// Primary +$primary-900: #004d3f; +$primary-800: #00695b; +$primary-700: #00796a; +$primary-600: #00897a; +$primary-500: $threema-green-color; // Standard +$primary-400: #26a699; +$primary-300: #4db6ab; +$primary-200: #80cbc3; +$primary-100: #b2dfdb; +$primary-050: #e0f2f1; +$primary: $primary-500; + +// Secondary +$secondary-999: rgba(0, 0, 0, 1); +$secondary-900: rgba(32, 32, 32, 1); +$secondary-800: rgba(66, 66, 66, 1); +$secondary-700: rgba(96, 96, 96, 1); +$secondary-600: rgba(116, 116, 116, 1); +$secondary-570: rgba(148, 148, 148, 1); +$secondary-500: rgba(157, 157, 157, 1); // Standard +$secondary-400: rgba(188, 188, 188, 1); +$secondary-320: rgba(219, 219, 219, 1); +$secondary-300: rgba(223, 223, 223, 1); +$secondary-200: rgba(237, 237, 237, 1); +$secondary-100: rgba(245, 245, 245, 1); +$secondary-050: rgba(250, 250, 250, 1); +$secondary-000: rgba(255, 255, 255, 1); +$secondary: $secondary-500; + +// Terniary + +// Material colors +$material-grey-color: $secondary-900; +$material-grey-inactive-color: lighter($material-grey-color, 50%); +$material-grey-dark-color: darken($secondary-900, 25%); +$material-card-shadow-color: px 2px 5px px $material-grey-dark-color, +px 2px 5px px $material-grey-dark-color; + +// Status colors +$status-ok-color: #4caf50; +$status-warning-color: #ff9800; +$status-error-color: #f44336; +$status-error-disabled-color: #f44336; +$status-starred-color: #ffc107; + +// Border colors +$border-dark-color: #ddd; +$border-light-color: $secondary-320; + +// Background colors +$background-dark-color: #efebe9; +$background-medium-color: #f5f5f5; +$background-light-color: $secondary-000; + +$background-emoji-picker-color: #efefef; +$navigation-background-color: $secondary-000; +$navigation-background-highlight-color: $background-medium-color; +$spinner-background-color: $background-light-color; + +$avatar-background-color: rgb(198, 198, 198); + +// Scrollbar colors +$scrollbar-thumb-color: #cccccc; +$scrollbar-background-color: $background-dark-color; + +// Header colors +$navigation-header-color: $secondary-800; +$conversation-header-color: #f6f6f6; + +// Text colors +$text-dark-color: $secondary-999; +$text-medium-color: $secondary-999; +$text-light-color: $secondary-300; + +$conversation-header-text-color: $material-grey-dark-color; + +$latest-message-text-color: $material-grey-color; +$text-placeholder-color: $middle-gray; +$text-protocol-updated-color: #9dd0f2; + +// md-toolbar colors +$md-toolbar-color: $navigation-header-color; +$md-toolbar-text-color: $secondary-000; +$md-toolbar-button-color: $secondary-000; + + +// Icon colors +$icon-color: $secondary-900; +$icon-dark-color: $material-grey-dark-color; +$icon-light-color: $secondary-000; +$icon-material-grey-color: $material-grey-color; + +// Message bubble colors +$message-quote-color: $threema-green-color; +$message-bubble-color-in: #f7f7f7; +$message-bubble-color-out: #dff0d8; +$ctrl-message-bubble-color: #fcf8e3; + +// Button colors +$button-color: $material-grey-color; +$button-color-enabled: rgb(250, 250, 250); +$button-color-disabled: rgba(255, 254, 254, .65); +$button-color-pressed: rgb(155, 155, 155); +$button-hover-color: rgba(158, 158, 158, .2); +$button-selected-color: rgba(158, 158, 158, 1); + +$button-text-dark-color: $secondary-999; +$button-text-light-color: $secondary-000; + +// Misc colors +$active-placeholder-color: #d3d3d3; +$url-light-blue-color: #288ac7; +$work-blue-color: #3b84df; +$white-zero: rgba(255, 255, 255, 0); + +.color-status-ok { + color: $status-ok-color; +} + +.color-status-warning { + color: $status-warning-color; +} + +.color-status-error { + color: $status-error-color; +} + +.material-icons.md-medium-dark { + color: $material-grey-color; +} + +.material-icons.md-medium-dark.md-inactive { + color: $material-grey-inactive-color; +} + +@import '../app'; diff --git a/src/services.ts b/src/services.ts index 4ead3ea9c..ca4a740c9 100644 --- a/src/services.ts +++ b/src/services.ts @@ -32,6 +32,7 @@ import {ReceiverService} from './services/receiver'; import {SettingsService} from './services/settings'; import {StateService} from './services/state'; import {StringService} from './services/string'; +import {ThemeService} from './services/theme'; import {TimeoutService} from './services/timeout'; import {TitleService} from './services/title'; import {UriService} from './services/uri'; @@ -54,6 +55,7 @@ angular.module('3ema.services', []) .service('StateService', StateService) .service('TimeoutService', TimeoutService) .service('TitleService', TitleService) +.service('ThemeService', ThemeService) .service('TrustedKeyStore', TrustedKeyStoreService) .service('WebClientService', WebClientService) .service('MimeService', MimeService) diff --git a/src/services/notification.ts b/src/services/notification.ts index a9d1087e5..a08014e4b 100644 --- a/src/services/notification.ts +++ b/src/services/notification.ts @@ -221,7 +221,6 @@ export class NotificationService { this.storeSetting(NotificationService.SETTINGS_NOTIFICATIONS, 'false'); } } - /** * Sets if the user wants a message preview */ diff --git a/src/services/theme.ts b/src/services/theme.ts new file mode 100644 index 000000000..30f9a679a --- /dev/null +++ b/src/services/theme.ts @@ -0,0 +1,93 @@ +/** + * This file is part of Threema Web. + * + * Threema Web is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero + * General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Threema Web. If not, see . + */ +import {SettingsService} from './settings'; + +export class ThemeService { + + public currentTheme: number; + + public themeOptions: string[] = ['THEME_LIGHT_WHITE', 'THEME_DARK_BLACK']; + private themeFilenames: string[] = ['app-light.css', 'app-dark.css']; + + private settingsService: SettingsService; + public static $inject = ['SettingsService']; + + constructor(settingsService: SettingsService) { + this.settingsService = settingsService; + this.currentTheme = this.getThemeID(); + } + + /* + * Returns a string with _dark added at the end. + * Used to get the correct icons depending on the theme. + */ + public themedFilename(fn: string): string { + if (fn == null) { + return null; + } + const ext = (this.currentTheme === 1) ? '_dark' : ''; + const fnl = fn.length; + return fn.substring(0, fnl - 4) + ext + fn.substring(fnl - 4, fnl); + } + + public setThemeID(themeID: number) { + this.currentTheme = themeID; + this.storeSetting('ThemeService.THEME_SETTING', themeID.toString()); + } + + public getThemeIDS(): number[] { + const list: number[] = []; + for (let i = 0; i < this.themeOptions.length; i++) { + list.push(i); + } + return list; + } + + public getThemeID(): number { + const theme: number = Number(this.retrieveSetting('ThemeService.THEME_SETTING')); + this.currentTheme = theme; + return isNaN(theme) ? 0 : theme; + } + + private getNameForThemeID(themeID: number): string { + if (themeID < this.themeOptions.length) { + return this.themeOptions[themeID]; + } + return this.themeOptions[0]; + } + + public getCSSForThemeID(themeID: number): string { + if (themeID < this.themeFilenames.length) { + return this.themeFilenames[themeID]; + } + return this.themeFilenames[0]; + } + + /** + * Stores the given key/value pair in local storage + */ + private storeSetting(key: string, value: string): void { + this.settingsService.storeUntrustedKeyValuePair(key, value); + } + + /** + * Retrieves the value for the given key from local storage + */ + private retrieveSetting(key: string): string { + return this.settingsService.retrieveUntrustedKeyValuePair(key); + } +} diff --git a/src/services/webclient.ts b/src/services/webclient.ts index f84ad750e..5aa1c6662 100644 --- a/src/services/webclient.ts +++ b/src/services/webclient.ts @@ -3155,7 +3155,7 @@ export class WebClientService { canChangeFirstName: true, canChangeLastName: true, }, - color: '#000000', + color: 'rgb(112, 112, 112)', }); this.registerInitializationStep(InitializationStep.Profile); diff --git a/tests/ui/compose_area.html b/tests/ui/compose_area.html index e05eecf6f..e0e53f407 100644 --- a/tests/ui/compose_area.html +++ b/tests/ui/compose_area.html @@ -20,7 +20,7 @@ - + diff --git a/tools/spinner/1-export.py b/tools/spinner/1-export.py index 3601e3fe1..21bbe7b06 100755 --- a/tools/spinner/1-export.py +++ b/tools/spinner/1-export.py @@ -31,12 +31,12 @@ def create_png(rotation: int) -> None: '-e', filename, '-w', '30', '-h', '30', + # '-b', 'rgb(48, 48, 48)', '-b', 'white', f.name, ]) result.check_returncode() - if __name__ == '__main__': with open('spinner.svg', 'r') as f: svg = f.read() diff --git a/tools/spinner/spinner_dark.svg b/tools/spinner/spinner_dark.svg new file mode 100644 index 000000000..ff96dbc65 --- /dev/null +++ b/tools/spinner/spinner_dark.svg @@ -0,0 +1,83 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/troubleshoot/index.html b/troubleshoot/index.html index c44fc3d70..d7cac8bab 100644 --- a/troubleshoot/index.html +++ b/troubleshoot/index.html @@ -58,7 +58,7 @@ } #wrapper { - background-color: white; + background-color: $background-medium-color; margin: 0 auto; padding: 16px 32px 32px; min-width: 400px;