diff --git a/package.json b/package.json index 6b0797074..4653677c2 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "monaco-editor": "^0.25.2", "mqtt": "4.3.7", "reflect-metadata": "^0.1.13", + "rxjs": "6.2.0", "sqlite3": "^5.0.4", "typedi": "^0.8.0", "typeorm": "^0.2.34", @@ -58,6 +59,7 @@ "vue-i18n": "^8.11.2", "vue-property-decorator": "^8.5.1", "vue-router": "^3.4.9", + "vue-rx": "6.2.0", "vue-virtual-scroller": "^1.0.10", "vuex": "^3.0.1", "vuex-class": "^0.3.2", @@ -71,7 +73,7 @@ "@types/fs-extra": "^8.0.0", "@types/lodash": "^4.14.142", "@types/mocha": "^5.2.7", - "@types/node": "^12.12.6", + "@types/node": "^14.16.0", "@types/sqlite3": "^3.1.8", "@types/ws": "^8.2.1", "@typescript-eslint/eslint-plugin": "^3.8.0", diff --git a/src/background.ts b/src/background.ts index a46c2a497..cd3b26164 100644 --- a/src/background.ts +++ b/src/background.ts @@ -104,6 +104,7 @@ async function createWindow() { autoCheck: setting.autoCheck, autoResub: setting.autoResub, autoScroll: setting.autoScroll, + autoScrollInterval: setting.autoScrollInterval, maxReconnectTimes: setting.maxReconnectTimes, syncOsTheme: setting.syncOsTheme, multiTopics: setting.multiTopics, diff --git a/src/database/database.config.ts b/src/database/database.config.ts index f23012dd4..49bfc165d 100644 --- a/src/database/database.config.ts +++ b/src/database/database.config.ts @@ -31,6 +31,7 @@ import { syncOsTheme1639730106721 } from './migration/1639730106721-syncOsTheme' import { topicDisabled1640846307653 } from './migration/1640846307653-topicDisabled' import { reconnectPeriod1642321826532 } from './migration/1642321826532-reconnectPeriod' import { multiTopics1659668384878 } from './migration/1659668384878-multiTopics' +import { autoScrollInterval1668415942736 } from './migration/1668415942736-autoScrollInterval' const STORE_PATH = getAppDataPath('MQTTX') try { @@ -69,6 +70,7 @@ const ORMConfig = { topicDisabled1640846307653, reconnectPeriod1642321826532, multiTopics1659668384878, + autoScrollInterval1668415942736, ], migrationsTableName: 'temp_migration_table', entities: [ diff --git a/src/database/migration/1668415942736-autoScrollInterval.ts b/src/database/migration/1668415942736-autoScrollInterval.ts new file mode 100644 index 000000000..6cc4daf94 --- /dev/null +++ b/src/database/migration/1668415942736-autoScrollInterval.ts @@ -0,0 +1,110 @@ +import { MigrationInterface, QueryRunner } from 'typeorm' + +export class autoScrollInterval1668415942736 implements MigrationInterface { + name = 'autoScrollInterval1668415942736' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + CREATE TABLE "temporary_SettingEntity" ( + "id" varchar PRIMARY KEY NOT NULL, + "width" integer NOT NULL DEFAULT (1025), + "height" integer NOT NULL DEFAULT (749), + "autoCheck" boolean NOT NULL DEFAULT (1), + "currentLang" varchar CHECK(currentLang IN ('zh', 'en', 'ja', 'tr', 'hu')) NOT NULL DEFAULT ('en'), + "currentTheme" varchar CHECK(currentTheme IN ('light', 'dark', 'night')) NOT NULL DEFAULT ('light'), + "maxReconnectTimes" integer NOT NULL DEFAULT (10), + "autoResub" boolean NOT NULL DEFAULT (1), + "autoScroll" boolean NOT NULL DEFAULT (1), + "syncOsTheme" boolean NOT NULL DEFAULT (0), + "multiTopics" boolean NOT NULL DEFAULT (1), + "autoScrollInterval" integer NOT NULL DEFAULT (1) + ) + `) + await queryRunner.query(` + INSERT INTO "temporary_SettingEntity"( + "id", + "width", + "height", + "autoCheck", + "currentLang", + "currentTheme", + "maxReconnectTimes", + "autoResub", + "autoScroll", + "syncOsTheme", + "multiTopics" + ) + SELECT "id", + "width", + "height", + "autoCheck", + "currentLang", + "currentTheme", + "maxReconnectTimes", + "autoResub", + "autoScroll", + "syncOsTheme", + "multiTopics" + FROM "SettingEntity" + `) + await queryRunner.query(` + DROP TABLE "SettingEntity" + `) + await queryRunner.query(` + ALTER TABLE "temporary_SettingEntity" + RENAME TO "SettingEntity" + `) + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + ALTER TABLE "SettingEntity" + RENAME TO "temporary_SettingEntity" + `) + await queryRunner.query(` + CREATE TABLE "SettingEntity" ( + "id" varchar PRIMARY KEY NOT NULL, + "width" integer NOT NULL DEFAULT (1025), + "height" integer NOT NULL DEFAULT (749), + "autoCheck" boolean NOT NULL DEFAULT (1), + "currentLang" varchar CHECK(currentLang IN ('zh', 'en', 'ja', 'tr', 'hu')) NOT NULL DEFAULT ('en'), + "currentTheme" varchar CHECK(currentTheme IN ('light', 'dark', 'night')) NOT NULL DEFAULT ('light'), + "maxReconnectTimes" integer NOT NULL DEFAULT (10), + "autoResub" boolean NOT NULL DEFAULT (1), + "autoScroll" boolean NOT NULL DEFAULT (1), + "syncOsTheme" boolean NOT NULL DEFAULT (0), + "multiTopics" boolean NOT NULL DEFAULT (1) + ) + `) + await queryRunner.query(` + INSERT INTO "SettingEntity"( + "id", + "width", + "height", + "autoCheck", + "currentLang", + "currentTheme", + "maxReconnectTimes", + "autoResub", + "autoScroll", + "syncOsTheme", + "multiTopics" + ) + SELECT "id", + "width", + "height", + "autoCheck", + "currentLang", + "currentTheme", + "maxReconnectTimes", + "autoResub", + "autoScroll", + "syncOsTheme", + "multiTopics" + FROM "temporary_SettingEntity" + `) + await queryRunner.query(` + DROP TABLE "temporary_SettingEntity" + `) + } +} diff --git a/src/database/models/SettingEntity.ts b/src/database/models/SettingEntity.ts index e8de2462a..92078c0b2 100644 --- a/src/database/models/SettingEntity.ts +++ b/src/database/models/SettingEntity.ts @@ -29,6 +29,9 @@ export default class SettingEntity { @Column({ type: 'boolean', default: true }) autoScroll!: boolean + @Column({ type: 'integer', default: 1 }) + autoScrollInterval!: number + @Column({ type: 'boolean', default: false }) syncOsTheme!: boolean diff --git a/src/lang/settings.ts b/src/lang/settings.ts index 1dcddb067..026034764 100644 --- a/src/lang/settings.ts +++ b/src/lang/settings.ts @@ -118,6 +118,13 @@ export default { ja: '自動スクロール', hu: 'Automatikus görgetés', }, + autoScrollInterval: { + zh: '自动滚动频率(秒)', + en: 'Auto scroll interval (seconds)', + tr: 'Otomatik kaydırma aralığı (saniye)', + ja: '自動スクロール間隔(秒)', + hu: 'Automatikus görgetési időköz (másodperc)', + }, multiTopics: { zh: '多主题订阅', en: 'Multi topics subscribe', diff --git a/src/main.ts b/src/main.ts index 73453ceb0..6b861f3d4 100644 --- a/src/main.ts +++ b/src/main.ts @@ -5,6 +5,7 @@ import VueClipboard from 'vue-clipboard2' import path from 'path' import log4js from 'log4js' import VueVirtualScroller from 'vue-virtual-scroller' +import VueRx from 'vue-rx' import 'element-ui/lib/theme-chalk/index.css' import ElementLocale from 'element-ui/lib/locale' @@ -36,6 +37,7 @@ ConnectionInit({ doMigrations: false, undoMigrations: false } as initOptionModel Vue.use(VueClipboard) Vue.use(VueLog4js, config) Vue.use(VueVirtualScroller) + Vue.use(VueRx) const locale: Language = store.state.app.currentLang const vueI18n: VueI18n = new VueI18n({ diff --git a/src/store/getter.ts b/src/store/getter.ts index 235dd3ad6..8dbabedb2 100644 --- a/src/store/getter.ts +++ b/src/store/getter.ts @@ -4,6 +4,7 @@ const getters = { autoCheck: (state: State) => state.app.autoCheck, autoResub: (state: State) => state.app.autoResub, autoScroll: (state: State) => state.app.autoScroll, + autoScrollInterval: (state: State) => state.app.autoScrollInterval, syncOsTheme: (state: State) => state.app.syncOsTheme, maxReconnectTimes: (state: State) => state.app.maxReconnectTimes, showSubscriptions: (state: State) => state.app.showSubscriptions, diff --git a/src/store/modules/app.ts b/src/store/modules/app.ts index b510796a4..5a2a8bbb2 100644 --- a/src/store/modules/app.ts +++ b/src/store/modules/app.ts @@ -7,6 +7,7 @@ const TOGGLE_LANG = 'TOGGLE_LANG' const TOGGLE_AUTO_CHECK = 'TOGGLE_AUTO_CHECK' const TOGGLE_AUTO_RESUB = 'TOGGLE_AUTO_RESUB' const TOGGLE_AUTO_SCROLL = 'TOGGLE_AUTO_SCROLL' +const SET_AUTO_SCROLL_INTERVAL = 'SET_AUTO_SCROLL_INTERVAL' const SET_MAX_RECONNECT_TIMES = 'SET_MAX_RECONNECT_TIMES' const CHANGE_ACTIVE_CONNECTION = 'CHANGE_ACTIVE_CONNECTION' const REMOVE_ACTIVE_CONNECTION = 'REMOVE_ACTIVE_CONNECTION' @@ -39,6 +40,7 @@ const app = { autoCheck: settingData.autoCheck, autoResub: settingData.autoResub, autoScroll: settingData.autoScroll, + autoScrollInterval: settingData.autoScrollInterval || 1, syncOsTheme: settingData.syncOsTheme, multiTopics: settingData.multiTopics, maxReconnectTimes: settingData.maxReconnectTimes || 10, @@ -68,6 +70,9 @@ const app = { [TOGGLE_AUTO_SCROLL](state: App, autoScroll: boolean) { state.autoScroll = autoScroll }, + [SET_AUTO_SCROLL_INTERVAL](state: App, autoScrollInterval: number) { + state.autoScrollInterval = autoScrollInterval + }, [TOGGLE_SYNC_OS_THEME](state: App, syncOsTheme: boolean) { state.syncOsTheme = syncOsTheme }, @@ -168,6 +173,12 @@ const app = { settingData.autoScroll = payload.autoScroll await settingService.update(payload) }, + async SET_AUTO_SCROLL_INTERVAL({ commit }: any, payload: App) { + const { settingService } = useServices() + commit(SET_AUTO_SCROLL_INTERVAL, payload.autoScrollInterval) + settingData.autoScrollInterval = payload.autoScrollInterval + await settingService.update(payload) + }, async TOGGLE_SYNC_OS_THEME({ commit }: any, payload: App) { const { settingService } = useServices() commit(TOGGLE_SYNC_OS_THEME, payload.syncOsTheme) diff --git a/src/types/global.d.ts b/src/types/global.d.ts index aef8e54e2..11174ebf8 100644 --- a/src/types/global.d.ts +++ b/src/types/global.d.ts @@ -91,6 +91,7 @@ declare global { autoCheck: boolean autoResub: boolean autoScroll: boolean + autoScrollInterval: number showSubscriptions: boolean syncOsTheme: boolean multiTopics: boolean diff --git a/src/views/connections/ConnectionsDetail.vue b/src/views/connections/ConnectionsDetail.vue index a8f9abf82..158a66345 100644 --- a/src/views/connections/ConnectionsDetail.vue +++ b/src/views/connections/ConnectionsDetail.vue @@ -282,6 +282,8 @@ import { Getter, Action } from 'vuex-class' import { ipcRenderer } from 'electron' import { MqttClient, IConnackPacket, IPublishPacket, IClientPublishOptions } from 'mqtt' import _ from 'lodash' +import { Subject } from 'rxjs' +import { throttleTime } from 'rxjs/operators' import time from '@/utils/time' import matchMultipleSearch from '@/utils/matchMultipleSearch' @@ -354,6 +356,7 @@ export default class ConnectionsDetail extends Vue { @Getter('activeConnection') private activeConnection!: ActiveConnection @Getter('showSubscriptions') private showSubscriptions!: boolean @Getter('autoScroll') private autoScroll!: boolean + @Getter('autoScrollInterval') private autoScrollInterval!: number @Getter('maxReconnectTimes') private maxReconnectTimes!: number @Getter('currentTheme') private theme!: Theme @Getter('showClientInfo') private clientInfoVisibles!: { [id: string]: boolean } @@ -432,6 +435,7 @@ export default class ConnectionsDetail extends Vue { private uptime = '' private bytesTimes = 0 private messagesAddedNewItem: boolean = false + private scrollSubject = new Subject() get titleName() { return this.record.name @@ -1018,6 +1022,10 @@ export default class ConnectionsDetail extends Vue { } // Scroll to page bottom + private scrollToBottomThrottle = () => { + this.scrollSubject.next() + } + private scrollToBottom() { if (this.autoScroll === false) { return @@ -1130,7 +1138,7 @@ export default class ConnectionsDetail extends Vue { this.unreadMessageIncrement({ id }) this.$log.info(`ID: ${id} received an unread message`) } - this.scrollToBottom() + this.scrollToBottomThrottle() } } // Set timed message success @@ -1457,6 +1465,13 @@ export default class ConnectionsDetail extends Vue { private created() { this.getConnectionValue(this.curConnectionId) + this.autoScroll && + this.scrollSubject + .asObservable() + .pipe(throttleTime(this.autoScrollInterval * 1000)) + .subscribe(() => { + this.scrollToBottom() + }) ipcRenderer.on('searchContent', () => { this.handleSearchOpen() }) @@ -1472,6 +1487,7 @@ export default class ConnectionsDetail extends Vue { private beforeDestroy() { ipcRenderer.removeAllListeners('searchContent') this.removeClinetsMessageListener() + this.scrollSubject.unsubscribe() this.stopTimedSend() window.onresize = null } diff --git a/src/views/settings/index.vue b/src/views/settings/index.vue index b776bc636..401a25c84 100644 --- a/src/views/settings/index.vue +++ b/src/views/settings/index.vue @@ -6,7 +6,7 @@ - + @@ -94,6 +94,20 @@ + + @@ -123,7 +137,7 @@ - + @@ -168,7 +182,7 @@ - + @@ -198,7 +212,7 @@
{{ $t('settings.advanced') }}
- + @@ -215,7 +229,7 @@ - + @@ -232,7 +246,7 @@ - + @@ -273,6 +287,9 @@ export default class Settings extends Vue { @Action('TOGGLE_AUTO_CHECK') private actionAutoCheck!: (payload: { autoCheck: boolean }) => void @Action('TOGGLE_AUTO_RESUB') private actionAutoResub!: (payload: { autoResub: boolean }) => void @Action('TOGGLE_AUTO_SCROLL') private actionAutoScroll!: (payload: { autoScroll: boolean }) => void + @Action('SET_AUTO_SCROLL_INTERVAL') private actionAutoScrollInterval!: (payload: { + autoScrollInterval: number + }) => void @Action('TOGGLE_SYNC_OS_THEME') private actionSyncOsTheme!: (payload: { syncOsTheme: boolean }) => void @Action('SET_MAX_RECONNECT_TIMES') private actionMaxReconnectTimes!: (payload: { maxReconnectTimes: number }) => void @Action('TOGGLE_MULTI_TOPICS') private actionToggleMultiTopics!: (payload: { multiTopics: boolean }) => void @@ -283,6 +300,7 @@ export default class Settings extends Vue { @Getter('syncOsTheme') private syncOsTheme!: boolean @Getter('maxReconnectTimes') private maxReconnectTimes!: number @Getter('autoScroll') private autoScroll!: boolean + @Getter('autoScrollInterval') private autoScrollInterval!: number @Getter('multiTopics') private multiTopics!: boolean private langOptions: Options[] = [ @@ -338,6 +356,10 @@ export default class Settings extends Vue { this.actionMaxReconnectTimes({ maxReconnectTimes: value }) } + private handleAutoScrollIntervalChange(value: number) { + this.actionAutoScrollInterval({ autoScrollInterval: value }) + } + private handleImportData() { this.showImportData = true } diff --git a/web/package.json b/web/package.json index c48b87eca..2f1519d80 100644 --- a/web/package.json +++ b/web/package.json @@ -20,6 +20,7 @@ "moment": "^2.29.4", "monaco-editor": "^0.25.2", "mqtt": "4.3.7", + "rxjs": "6.2.0", "vue": "~2.6.10", "vue-class-component": "^7.0.2", "vue-click-outside": "^1.1.0", @@ -28,6 +29,7 @@ "vue-i18n": "^8.11.2", "vue-property-decorator": "^8.1.0", "vue-router": "^3.4.9", + "vue-rx": "6.2.0", "vue-virtual-scroller": "^1.0.10", "vuex": "^3.0.1", "vuex-class": "^0.3.2" diff --git a/web/src/database/index.ts b/web/src/database/index.ts index 3fffec2ae..86f64eeb5 100644 --- a/web/src/database/index.ts +++ b/web/src/database/index.ts @@ -44,6 +44,10 @@ class DB { }) .write() } + // Set auto scroll interval to 1 second by default + if (!this.db.has('settings.autoScrollInterval').value()) { + this.db.set('settings.autoScrollInterval', 1).write() + } // Set max reconnection times if (!this.db.get('settings.maxReconnectTimes').value()) { this.db.set('settings.maxReconnectTimes', 10).write() diff --git a/web/src/lang/settings.ts b/web/src/lang/settings.ts index 1e7f5d2f4..f28ecabf3 100644 --- a/web/src/lang/settings.ts +++ b/web/src/lang/settings.ts @@ -69,6 +69,11 @@ export default { en: 'Whether to automatically scroll the list of messages', ja: 'メッセージリストを自動的にスクロールするかどうか', }, + autoScrollInterval: { + zh: '自动滚动频率(秒)', + en: 'Auto scroll interval (seconds)', + ja: '自動スクロール間隔(秒)', + }, multiTopics: { zh: '多主题订阅', en: 'Multi topics subscribe', diff --git a/web/src/main.ts b/web/src/main.ts index 544df9cdc..0cc60e6c8 100644 --- a/web/src/main.ts +++ b/web/src/main.ts @@ -10,12 +10,14 @@ import VueClipboard from 'vue-clipboard2' import Lang from './lang' import element from './utils/element' import VueVirtualScroller from 'vue-virtual-scroller' +import VueRx from 'vue-rx' import VueGtag from 'vue-gtag' Vue.use(element) Vue.use(VueI18n) Vue.use(VueClipboard) Vue.use(VueVirtualScroller) +Vue.use(VueRx) Vue.use( VueGtag, { diff --git a/web/src/store/getter.ts b/web/src/store/getter.ts index 7c190acc3..476620197 100644 --- a/web/src/store/getter.ts +++ b/web/src/store/getter.ts @@ -4,6 +4,7 @@ const getters = { autoCheck: (state: State) => state.app.autoCheck, autoResub: (state: State) => state.app.autoResub, autoScroll: (state: State) => state.app.autoScroll, + autoScrollInterval: (state: State) => state.app.autoScrollInterval, maxReconnectTimes: (state: State) => state.app.maxReconnectTimes, showSubscriptions: (state: State) => state.app.showSubscriptions, activeConnection: (state: State) => state.app.activeConnection, diff --git a/web/src/store/modules/app.ts b/web/src/store/modules/app.ts index a4000fa1b..0f006179b 100644 --- a/web/src/store/modules/app.ts +++ b/web/src/store/modules/app.ts @@ -6,6 +6,7 @@ const TOGGLE_LANG = 'TOGGLE_LANG' const TOGGLE_AUTO_CHECK = 'TOGGLE_AUTO_CHECK' const TOGGLE_AUTO_RESUB = 'TOGGLE_AUTO_RESUB' const TOGGLE_AUTO_SCROLL = 'TOGGLE_AUTO_SCROLL' +const SET_AUTO_SCROLL_INTERVAL = 'SET_AUTO_SCROLL_INTERVAL' const SET_MAX_RECONNECT_TIMES = 'SET_MAX_RECONNECT_TIMES' const CHANGE_ACTIVE_CONNECTION = 'CHANGE_ACTIVE_CONNECTION' const REMOVE_ACTIVE_CONNECTION = 'REMOVE_ACTIVE_CONNECTION' @@ -35,6 +36,7 @@ const app = { autoCheck: stateRecord.autoCheck, autoResub: stateRecord.autoResub, autoScroll: stateRecord.autoScroll, + autoScrollInterval: stateRecord.autoScrollInterval, multiTopics: stateRecord.multiTopics, maxReconnectTimes: stateRecord.maxReconnectTimes || 10, showSubscriptions: getShowSubscriptions(), @@ -61,6 +63,9 @@ const app = { [TOGGLE_AUTO_SCROLL](state: App, autoScroll: boolean) { state.autoScroll = autoScroll }, + [SET_AUTO_SCROLL_INTERVAL](state: App, autoScrollInterval: number) { + state.autoScrollInterval = autoScrollInterval + }, [TOGGLE_MULTI_TOPICS](state: App, multiTopics: boolean) { state.multiTopics = multiTopics }, @@ -141,6 +146,10 @@ const app = { setSettings('settings.autoScroll', payload.autoScroll) commit(TOGGLE_AUTO_SCROLL, payload.autoScroll) }, + SET_AUTO_SCROLL_INTERVAL({ commit }: any, payload: App) { + setSettings('settings.autoScrollInterval', payload.autoScrollInterval) + commit(SET_AUTO_SCROLL_INTERVAL, payload.autoScrollInterval) + }, TOGGLE_MULTI_TOPICS({ commit }: any, payload: App) { setSettings('settings.multiTopics', payload.multiTopics) commit(TOGGLE_MULTI_TOPICS, payload.multiTopics) diff --git a/web/src/types/global.d.ts b/web/src/types/global.d.ts index a8faf661a..d930944bf 100644 --- a/web/src/types/global.d.ts +++ b/web/src/types/global.d.ts @@ -118,6 +118,7 @@ declare global { autoCheck: boolean autoResub: boolean autoScroll: boolean + autoScrollInterval: number showSubscriptions: boolean multiTopics: boolean maxReconnectTimes: number diff --git a/web/src/views/connections/ConnectionsDetail.vue b/web/src/views/connections/ConnectionsDetail.vue index 08058e577..8e799966c 100644 --- a/web/src/views/connections/ConnectionsDetail.vue +++ b/web/src/views/connections/ConnectionsDetail.vue @@ -197,8 +197,10 @@ import { Component, Vue, Prop, Watch } from 'vue-property-decorator' import { Getter, Action } from 'vuex-class' import { TranslateResult } from 'vue-i18n' -import mqtt, { MqttClient, IPublishPacket, IClientPublishOptions } from 'mqtt' +import { MqttClient, IPublishPacket, IClientPublishOptions } from 'mqtt' import _ from 'lodash' +import { Subject } from 'rxjs' +import { throttleTime } from 'rxjs/operators' import { deleteConnection, updateConnection, updateConnectionMessage } from '@/utils/api/connection' import time from '@/utils/time' @@ -253,6 +255,7 @@ export default class ConnectionsDetail extends Vue { @Getter('activeConnection') private activeConnection: $TSFixed @Getter('showSubscriptions') private showSubscriptions!: boolean @Getter('autoScroll') private autoScroll!: boolean + @Getter('autoScrollInterval') private autoScrollInterval!: number @Getter('maxReconnectTimes') private maxReconnectTimes!: number @Getter('currentTheme') private theme!: Theme @Getter('showClientInfo') private clientInfoVisibles!: { @@ -314,6 +317,7 @@ export default class ConnectionsDetail extends Vue { '3.1.1': 4, '5.0': 5, } + private scrollSubject = new Subject() // Connect public connect(): boolean | void { @@ -777,7 +781,7 @@ export default class ConnectionsDetail extends Vue { updateConnectionMessage(id, { ...receivedMessage }) this.unreadMessageIncrement({ id }) } - this.scrollToBottom() + this.scrollToBottomThrottle() } } @@ -878,6 +882,10 @@ export default class ConnectionsDetail extends Vue { } // Scroll to page bottom + private scrollToBottomThrottle = () => { + this.scrollSubject.next() + } + private scrollToBottom() { if (this.autoScroll === false) { return @@ -957,9 +965,13 @@ export default class ConnectionsDetail extends Vue { private created() { const { id } = this.$route.params this.getConnectionValue(id) - // ipcRenderer.on('searchByTopic', () => { - // this.handleSearchOpen() - // }) + this.autoScroll && + this.scrollSubject + .asObservable() + .pipe(throttleTime(this.autoScrollInterval * 1000)) + .subscribe(() => { + this.scrollToBottom() + }) } private mounted() { @@ -1014,6 +1026,7 @@ export default class ConnectionsDetail extends Vue { private beforeDestroy() { // ipcRenderer.removeAllListeners('searchByTopic') this.removeClinetsMessageListener() + this.scrollSubject.unsubscribe() } } diff --git a/web/src/views/settings/index.vue b/web/src/views/settings/index.vue index 08522703f..d6a60fec3 100644 --- a/web/src/views/settings/index.vue +++ b/web/src/views/settings/index.vue @@ -6,7 +6,7 @@ - + @@ -77,6 +77,20 @@ + + @@ -106,7 +120,7 @@ - + @@ -124,7 +138,7 @@ - + @@ -157,16 +171,21 @@ export default class Settings extends Vue { @Action('SET_MAX_RECONNECT_TIMES') private actionMaxReconnectTimes!: (payload: { maxReconnectTimes: number }) => void @Action('TOGGLE_AUTO_RESUB') private actionAutoResub!: (payload: { autoResub: boolean }) => void @Action('TOGGLE_AUTO_SCROLL') private actionAutoScroll!: (payload: { autoScroll: boolean }) => void + @Action('SET_AUTO_SCROLL_INTERVAL') private actionAutoScrollInterval!: (payload: { + autoScrollInterval: number + }) => void @Action('TOGGLE_MULTI_TOPICS') private actionToggleMultiTopics!: (payload: { multiTopics: boolean }) => void @Getter('currentTheme') private getterTheme!: 'light' | 'dark' | 'night' @Getter('currentLang') private getterLang!: Language @Getter('maxReconnectTimes') private getterMaxReconnectTimes!: number @Getter('autoResub') private autoResub!: boolean @Getter('autoScroll') private autoScroll!: boolean + @Getter('autoScrollInterval') private getterAutoScrollInterval!: number @Getter('multiTopics') private multiTopics!: boolean private currentTheme: 'light' | 'dark' | 'night' = 'light' private currentLang: Language = 'en' + private autoScrollInterval = 1 private maxReconnectTimes = 10 private langOptions: Options[] = [ { label: '简体中文', value: 'zh' }, @@ -206,9 +225,14 @@ export default class Settings extends Vue { this.actionMaxReconnectTimes({ maxReconnectTimes: value }) } + private handleAutoScrollIntervalChange(value: number) { + this.actionAutoScrollInterval({ autoScrollInterval: value }) + } + private created() { this.currentTheme = this.getterTheme this.currentLang = this.getterLang + this.autoScrollInterval = this.getterAutoScrollInterval this.maxReconnectTimes = this.getterMaxReconnectTimes } } diff --git a/web/yarn.lock b/web/yarn.lock index bdab0ba22..d443c2656 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -8193,6 +8193,13 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" +rxjs@6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.2.0.tgz#e024d0e180b72756a83c2aaea8f25423751ba978" + integrity sha512-qBzf5uu6eOKiCZuAE0SgZ0/Qp+l54oeVxFfC2t+mJ2SFI6IB8gmMdJHs5DUMu5kqifqcCtsKS2XHjhZu6RKvAw== + dependencies: + tslib "^1.9.0" + rxjs@^5.0.0-beta.11: version "5.5.12" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.12.tgz#6fa61b8a77c3d793dbaf270bee2f43f652d741cc" @@ -9631,6 +9638,11 @@ vue-router@^3.4.9: resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.5.4.tgz#c453c0b36bc75554de066fefc3f2a9c3212aca70" integrity sha512-x+/DLAJZv2mcQ7glH2oV9ze8uPwcI+H+GgTgTmb5I55bCgY3+vXWIsqbYUzbBSZnwFHEJku4eoaH/x98veyymQ== +vue-rx@6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/vue-rx/-/vue-rx-6.2.0.tgz#c3b86462b252626edd16417385bb9054a3a23acb" + integrity sha512-tpKUcqS5IUYS+HsdbR5TlE5LL9PK4zwlplEtmMeydnbqaUTa9ciLMplJXAtFSiQw1vuURoyEJmCXqMxaVEIloQ== + vue-style-loader@^4.1.0: version "4.1.3" resolved "https://registry.yarnpkg.com/vue-style-loader/-/vue-style-loader-4.1.3.tgz#6d55863a51fa757ab24e89d9371465072aa7bc35" diff --git a/yarn.lock b/yarn.lock index 335c15a01..2e8ef3717 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1147,10 +1147,10 @@ resolved "https://registry.npmjs.org/@types/node/-/node-15.12.2.tgz#1f2b42c4be7156ff4a6f914b2fb03d05fa84e38d" integrity sha512-zjQ69G564OCIWIOHSXyQEEDpdpGl+G348RAKY0XXy9Z5kU9Vzv1GMNnkar/ZJ8dzXB3COzD9Mo9NtRZ4xfgUww== -"@types/node@^12.12.6": - version "12.20.15" - resolved "https://registry.npmjs.org/@types/node/-/node-12.20.15.tgz#10ee6a6a3f971966fddfa3f6e89ef7a73ec622df" - integrity sha512-F6S4Chv4JicJmyrwlDkxUdGNSplsQdGwp1A0AJloEVDirWdZOAiRHhovDlsFkKUrquUXhz1imJhXHsf59auyAg== +"@types/node@^14.16.0": + version "14.18.33" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.33.tgz#8c29a0036771569662e4635790ffa9e057db379b" + integrity sha512-qelS/Ra6sacc4loe/3MSjXNL1dNQ/GjxNHVzuChwMfmk7HuycRLVQN2qNY3XahK+fZc5E2szqQSKUyAF0E+2bg== "@types/node@^14.6.2": version "14.17.29" @@ -10308,6 +10308,13 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" +rxjs@6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.2.0.tgz#e024d0e180b72756a83c2aaea8f25423751ba978" + integrity sha512-qBzf5uu6eOKiCZuAE0SgZ0/Qp+l54oeVxFfC2t+mJ2SFI6IB8gmMdJHs5DUMu5kqifqcCtsKS2XHjhZu6RKvAw== + dependencies: + tslib "^1.9.0" + rxjs@^5.0.0-beta.11: version "5.5.12" resolved "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz#6fa61b8a77c3d793dbaf270bee2f43f652d741cc" @@ -12153,6 +12160,11 @@ vue-router@^3.4.9: resolved "https://registry.npmjs.org/vue-router/-/vue-router-3.5.1.tgz#edf3cf4907952d1e0583e079237220c5ff6eb6c9" integrity sha512-RRQNLT8Mzr8z7eL4p7BtKvRaTSGdCbTy2+Mm5HTJvLGYSSeG9gDzNasJPP/yOYKLy+/cLG/ftrqq5fvkFwBJEw== +vue-rx@6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/vue-rx/-/vue-rx-6.2.0.tgz#c3b86462b252626edd16417385bb9054a3a23acb" + integrity sha512-tpKUcqS5IUYS+HsdbR5TlE5LL9PK4zwlplEtmMeydnbqaUTa9ciLMplJXAtFSiQw1vuURoyEJmCXqMxaVEIloQ== + vue-style-loader@^4.1.0, vue-style-loader@^4.1.2: version "4.1.3" resolved "https://registry.yarnpkg.com/vue-style-loader/-/vue-style-loader-4.1.3.tgz#6d55863a51fa757ab24e89d9371465072aa7bc35"