diff --git a/.circleci/config.yml b/.circleci/config.yml index c2b67fe5..1cf7585f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -6,6 +6,11 @@ jobs: working_directory: /var/opt/app steps: - checkout + - run: + name: python + command: | + apt-get update + apt-get install -y python build-essential libfontconfig-dev - restore_cache: name: Restoring cache - node_modules keys: diff --git a/README.md b/README.md index b7714a13..04c7f87c 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,9 @@ We'd love you to contribute to Whalebird. $ git clone https://github.com/h3poteto/whalebird-desktop.git $ cd whalebird-desktop +# Install font config +$ sudo apt-get install libfontconfig-dev + # install dependencies $ npm install diff --git a/package-lock.json b/package-lock.json index 73fc5d47..812e3442 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3245,6 +3245,12 @@ "restore-cursor": "^2.0.0" } }, + "cli-spinners": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-1.3.1.tgz", + "integrity": "sha512-1QL4544moEsDVH9T/l6Cemov/37iv1RtoKf7NJ04A60+4MREXNfx/QvavbH6QoGdsD4N4Mwy49cmaINR/o2mdg==", + "dev": true + }, "cli-width": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", @@ -4440,6 +4446,12 @@ "repeating": "^2.0.0" } }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "dev": true + }, "detect-node": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.3.tgz", @@ -5161,6 +5173,129 @@ "mime": "^2.3.1" } }, + "electron-rebuild": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/electron-rebuild/-/electron-rebuild-1.8.2.tgz", + "integrity": "sha512-EeR4dgb6NN7ybxduUWMeeLhU/EuF+FzwFZJfMJXD0bx96K+ttAieCXOn9lTO5nA9Qn3hiS7pEpk8pZ9StpGgSg==", + "dev": true, + "requires": { + "colors": "^1.2.0", + "debug": "^2.6.3", + "detect-libc": "^1.0.3", + "fs-extra": "^3.0.1", + "node-abi": "^2.0.0", + "node-gyp": "^3.6.0", + "ora": "^1.2.0", + "rimraf": "^2.6.1", + "spawn-rx": "^2.0.10", + "yargs": "^7.0.2" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "colors": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.2.tgz", + "integrity": "sha512-rhP0JSBGYvpcNQj4s5AdShMeE5ahMop96cTeDl/v9qQQm2fYClE2QXZRi8wLzc+GmXSxdIqqbOIAhyObEXDbfQ==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "fs-extra": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz", + "integrity": "sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^3.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz", + "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "os-locale": { + "version": "1.4.0", + "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "^1.0.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yargs": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", + "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.0" + } + }, + "yargs-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", + "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", + "dev": true, + "requires": { + "camelcase": "^3.0.0" + } + } + } + }, "electron-to-chromium": { "version": "1.3.52", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.52.tgz", @@ -6789,6 +6924,14 @@ "debug": "^3.1.0" } }, + "font-manager": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/font-manager/-/font-manager-0.3.0.tgz", + "integrity": "sha512-6N3pzO+9kxE3yD9c4VN7reg5fqgFvjcUdxZmwauRzsExaeKRu0APfEi3DOISFakokybgKlZcLFQHawwc2TMpQQ==", + "requires": { + "nan": ">=2.10.0" + } + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -11018,8 +11161,7 @@ "nan": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", - "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", - "dev": true + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==" }, "nanomatch": { "version": "1.2.13", @@ -11107,6 +11249,15 @@ "lower-case": "^1.1.1" } }, + "node-abi": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.4.4.tgz", + "integrity": "sha512-DQ9Mo2mf/XectC+s6+grPPRQ1Z9gI3ZbrGv6nyXRkjwT3HrE0xvtvrfnH7YHYBLgC/KLadg+h3XHnhZw1sv88A==", + "dev": true, + "requires": { + "semver": "^5.4.1" + } + }, "node-fetch": { "version": "1.6.3", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.6.3.tgz", @@ -11734,6 +11885,18 @@ "wordwrap": "~1.0.0" } }, + "ora": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-1.4.0.tgz", + "integrity": "sha512-iMK1DOQxzzh2MBlVsU42G80mnrvUhqsMh74phHtDlrcTZPK0pH6o7l7DRshK+0YsxDyEuaOkziVdvM3T0QTzpw==", + "dev": true, + "requires": { + "chalk": "^2.1.0", + "cli-cursor": "^2.1.0", + "cli-spinners": "^1.0.1", + "log-symbols": "^2.1.0" + } + }, "original": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/original/-/original-1.0.1.tgz", @@ -14778,6 +14941,28 @@ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", "dev": true }, + "spawn-rx": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/spawn-rx/-/spawn-rx-2.0.12.tgz", + "integrity": "sha512-gOPXiQQFQ9lTOLuys0iMn3jfxxv9c7zzwhbYLOEbQGvEShHVJ5sSR1oD3Daj88os7jKArDYT7rbOKdvNhe7iEg==", + "dev": true, + "requires": { + "debug": "^2.5.1", + "lodash.assign": "^4.2.0", + "rxjs": "^5.1.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, "spdx-correct": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", diff --git a/package.json b/package.json index 40ea5aa2..b3032463 100644 --- a/package.json +++ b/package.json @@ -38,8 +38,9 @@ "pack:renderer": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.renderer.config.js", "test": "npm run unit && npm run e2e", "unit": "karma start test/unit/karma.conf.js", - "postinstall": "npm run lint:fix", - "mocha": "BABEL_ENV=test mocha --require babel-register --recursive ./test/mocha/**/*.js" + "postinstall": "npm run lint:fix && npm run electron-rebuild", + "mocha": "BABEL_ENV=test mocha --require babel-register --recursive ./test/mocha/**/*.js", + "electron-rebuild": "./node_modules/.bin/electron-rebuild" }, "build": { "productName": "Whalebird", @@ -104,6 +105,7 @@ "electron-window-state": "^4.1.1", "element-ui": "^2.4.7", "emojilib": "^2.3.0", + "font-manager": "^0.3.0", "hawk": "^7.0.7", "hoek": "^5.0.3", "i18next": "^11.5.0", @@ -153,6 +155,7 @@ "electron-debug": "^1.4.0", "electron-devtools-installer": "^2.2.4", "electron-packager": "^12.0.2", + "electron-rebuild": "^1.8.2", "eslint": "^5.2.0", "eslint-config-standard": "^12.0.0-alpha.0", "eslint-friendly-formatter": "^4.0.1", diff --git a/src/config/locales/de/translation.json b/src/config/locales/de/translation.json index c9ff8ed6..08283b40 100644 --- a/src/config/locales/de/translation.json +++ b/src/config/locales/de/translation.json @@ -116,6 +116,7 @@ "wrapper_mask_color": "Modal wrapper" }, "font_size": "Schriftgröße", + "font_family": "Font family", "display_style": { "title": "Anzeigestil", "display_name_and_username": "Anzeige- und Benutzername", diff --git a/src/config/locales/en/translation.json b/src/config/locales/en/translation.json index 8acfda6c..578c574e 100644 --- a/src/config/locales/en/translation.json +++ b/src/config/locales/en/translation.json @@ -116,6 +116,7 @@ "wrapper_mask_color": "Modal wrapper" }, "font_size": "Font size", + "font_family": "Font family", "display_style": { "title": "Display style of username", "display_name_and_username": "Display name and username", diff --git a/src/config/locales/fr/translation.json b/src/config/locales/fr/translation.json index f88a48a2..372b2050 100644 --- a/src/config/locales/fr/translation.json +++ b/src/config/locales/fr/translation.json @@ -116,6 +116,7 @@ "wrapper_mask_color": "Modal wrapper" }, "font_size": "Taille des caractères", + "font_family": "Font family", "display_style": { "title": "Format d'affichage", "display_name_and_username": "Nom et utilisateur⋅trice", diff --git a/src/config/locales/ja/translation.json b/src/config/locales/ja/translation.json index 63af2e66..8dcfc7a7 100644 --- a/src/config/locales/ja/translation.json +++ b/src/config/locales/ja/translation.json @@ -116,6 +116,7 @@ "wrapper_mask_color": "モーダル背景" }, "font_size": "フォントサイズ", + "font_family": "フォント", "display_style": { "title": "ユーザ名の表示形式", "display_name_and_username": "表示名+ユーザー名", diff --git a/src/config/locales/ko/translation.json b/src/config/locales/ko/translation.json index d6b75cb4..c956779d 100644 --- a/src/config/locales/ko/translation.json +++ b/src/config/locales/ko/translation.json @@ -76,9 +76,9 @@ "title": "일반", "toot": { "title": "툿", - "description": "Customize default visibility of toot.", + "description": "툿의 기본 공개범위를 변경합니다.", "visibility": { - "title": "기본 공개 설정", + "title": "기본 공개 범위 설정", "public": "공개", "unlisted": "미등록", "private": "비공개", @@ -87,9 +87,9 @@ }, "sounds": { "title": "사운드", - "description": "Please set feedback sounds.", - "fav_rb": "When you favorite or boost the toot", - "toot": "When you post toot" + "description": "피드백 소리를 설정해 주세요.", + "fav_rb": "툿을 즐겨찾기하거나 부스트 했을 때", + "toot": "새 툿을 보낼 때" } }, "appearance": { @@ -101,21 +101,22 @@ "solarized_light": "SolarizedLight", "solarized_dark": "SolarizedDark", "kimbie_dark": "KimbieDark", - "custom": "Custom" + "custom": "사용자 설정" }, "custom_theme": { - "background_color": "Base background", - "selected_background_color": "Focused background", - "global_header_color": "Account menu", - "side_menu_color": "Side menu", - "primary_color": "Primary font", - "regular_color": "Regular font", - "secondary_color": "Secondary font", - "border_color": "Border", - "header_menu_color": "Header menu", - "wrapper_mask_color": "Modal wrapper" + "background_color": "기본 배경 색상", + "selected_background_color": "선택 배경 색상", + "global_header_color": "계정 메뉴 색상", + "side_menu_color": "사이드 바 색상", + "primary_color": "기본 글꼴 색상", + "regular_color": "레귤러 글꼴 색상", + "secondary_color": "보조 글꼴 색상", + "border_color": "경계선 색상", + "header_menu_color": "헤더 메뉴 색상", + "wrapper_mask_color": "모달 랩퍼 색상" }, "font_size": "폰트 크기", + "font_family": "Font family", "display_style": { "title": "사용자 표시 형식", "display_name_and_username": "닉네임과 아이디 모두 보이기", @@ -131,11 +132,11 @@ "notification": { "title": "알림", "enable": { - "description": "Please set notification events.", - "reply": "Notify me when I receive reply", - "reblog": "Notify me when I receive reblog", - "favourite": "Notify me when I receive favourite", - "follow": "Notify me when I receive follow" + "description": "알림 범위를 설정해 주세요.", + "reply": "답장을 받았을 때 알림을 받습니다", + "reblog": "누군가 부스트했을 때 알림을 받습니다", + "favourite": "누군가 즐겨찾기 했을 때 알림을 받습니다", + "follow": "누군가 나를 팔로우 했을 때 알림을 받습니다" } }, "account": { @@ -153,7 +154,7 @@ }, "language": { "title": "언어", - "language_description": "Choose the language you would like to use with Whalebird.", + "language_description": "Whalebird에서 사용할 언어를 선택해 주세요.", "notice": "재실행이 필요합니다", "confirm": { "title": "알림", @@ -177,7 +178,7 @@ "change_visibility": "공개 범위 변경", "add_cw": "경고 문구 추가", "change_sensitive": "민감한 미디어 설정", - "pined_hashtag": "Pin the hashtag" + "pined_hashtag": "해시태그고정" }, "jump": { "jump_to": "이동" @@ -190,10 +191,10 @@ "title": "리스트 멤버" }, "mute_confirm": { - "title": "Are you sure to mute?", - "body": "Hide notification from this user?", - "cancel": "Cancel", - "ok": "Mute" + "title": "정말로 뮤트하시겠습니까?", + "body": "이 사용자로부터의 모든 알림이 꺼집니다.", + "cancel": "취소", + "ok": "뮤트" }, "shortcut": { "title": "키보드 단축키", @@ -239,10 +240,10 @@ "follow_requested": "팔로우 요청중", "open_in_browser": "브라우저에서 열기", "manage_list_memberships": "리스트 멤버 관리", - "mute": "Mute", - "unmute": "Unmute", - "unblock": "Unblock", - "block": "Block", + "mute": "뮤트", + "unmute": "뮤트 해제", + "unblock": "차단 해제", + "block": "차단", "toots": "툿", "follows": "팔로잉", "followers": "팔로워" @@ -250,8 +251,8 @@ }, "hashtag": { "tag_name": "태그 이름", - "delete_tag": "Delete tag", - "save_tag": "Save tag" + "delete_tag": "태그 삭제", + "save_tag": "태그 저장" }, "search": { "search": "검색", diff --git a/src/config/locales/pl/translation.json b/src/config/locales/pl/translation.json index 4130851c..bfe143e6 100644 --- a/src/config/locales/pl/translation.json +++ b/src/config/locales/pl/translation.json @@ -116,6 +116,7 @@ "wrapper_mask_color": "Modal wrapper" }, "font_size": "Rozmiar czcionki", + "font_family": "Font family", "display_style": { "title": "Styl wyświetlania", "display_name_and_username": "Nazwa wyświetlana i nazwa użytkownika", diff --git a/src/main/fonts.js b/src/main/fonts.js new file mode 100644 index 00000000..a604bf43 --- /dev/null +++ b/src/main/fonts.js @@ -0,0 +1,14 @@ +import fontManager from 'font-manager' + +const fonts = () => { + return new Promise((resolve, reject) => { + fontManager.getAvailableFonts((fonts) => { + const families = fonts.map(f => { + return f.family + }) + resolve(Array.from(new Set(families)).sort()) + }) + }) +} + +export default fonts diff --git a/src/main/index.js b/src/main/index.js index c02ce8d1..b7646cf1 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -15,6 +15,7 @@ import Authentication from './auth' import Account from './account' import Streaming from './streaming' import Preferences from './preferences' +import Fonts from './fonts' import Hashtags from './hashtags' import i18n from '../config/i18n' import Language from '../constants/language' @@ -690,6 +691,17 @@ ipcMain.on('remove-hashtag', (event, tag) => { }) }) +// Fonts +ipcMain.on('list-fonts', (event, _) => { + Fonts() + .then(list => { + event.sender.send('response-list-fonts', list) + }) + .catch(err => { + event.sender.send('error-list-fonts', err) + }) +}) + // Application control ipcMain.on('relaunch', (event, _) => { app.relaunch() diff --git a/src/main/preferences.js b/src/main/preferences.js index 350ad5c2..da29b0ff 100644 --- a/src/main/preferences.js +++ b/src/main/preferences.js @@ -6,6 +6,7 @@ import Theme from '../constants/theme' import Language from '../constants/language' import TimeFormat from '../constants/timeFormat' import { LightTheme } from '../renderer/utils/theme' +import DefaultFonts from '../renderer/utils/fonts' const Base = { general: { @@ -34,7 +35,8 @@ const Base = { fontSize: 14, displayNameStyle: DisplayStyle.DisplayNameAndUsername.value, timeFormat: TimeFormat.Absolute.value, - customThemeColor: LightTheme + customThemeColor: LightTheme, + font: DefaultFonts[0] } } diff --git a/src/renderer/App.vue b/src/renderer/App.vue index 95a8ae40..593ff017 100644 --- a/src/renderer/App.vue +++ b/src/renderer/App.vue @@ -23,7 +23,8 @@ export default { '--theme-border-color': state.App.theme.border_color, '--theme-header-menu-color': state.App.theme.header_menu_color, '--theme-wrapper-mask-color': state.App.theme.wrapper_mask_color, - '--base-font-size': `${state.App.fontSize}px` + '--base-font-size': `${state.App.fontSize}px`, + '--specified-fonts': state.App.defaultFonts.join(', ') } } }) @@ -42,20 +43,6 @@ export default {