From 200c82499d9f15ee0f87462f4ce965dc6f44b4e0 Mon Sep 17 00:00:00 2001 From: Maya Date: Thu, 18 Mar 2021 00:29:56 +0100 Subject: [PATCH] 3.0.16 --- bbcode/core.ts | 15 ++++++++- bbcode/editor.ts | 6 ++++ bbcode/parser.ts | 12 +++---- chat/Logs.vue | 31 +++++++++++++------ chat/common.ts | 10 +++--- chat/core.ts | 9 ++---- chat/localize.ts | 3 +- electron/Index.vue | 4 +-- electron/pack.js | 4 +-- electron/package.json | 2 +- mobile/Index.vue | 2 +- mobile/android/.idea/misc.xml | 2 +- mobile/android/.idea/modules.xml | 4 +-- mobile/android/app/build.gradle | 6 ++-- mobile/android/build.gradle | 4 +-- .../gradle/wrapper/gradle-wrapper.properties | 2 +- mobile/ios/F-Chat.xcodeproj/project.pbxproj | 11 +++++-- mobile/ios/F-Chat/AppDelegate.swift | 7 +---- mobile/ios/F-Chat/Background.swift | 2 +- mobile/ios/F-Chat/Notification.swift | 10 +++--- mobile/ios/F-Chat/ViewController.swift | 15 +++++---- mobile/package.json | 4 +-- webchat/chat.ts | 4 +-- webchat/package.json | 4 +-- webchat/webpack.config.js | 4 +-- 25 files changed, 104 insertions(+), 73 deletions(-) diff --git a/bbcode/core.ts b/bbcode/core.ts index 0196191..12bd1c9 100644 --- a/bbcode/core.ts +++ b/bbcode/core.ts @@ -79,6 +79,19 @@ export class CoreBBCodeParser extends BBCodeParser { element.appendChild(span); return element; })); + this.addTag(new BBCodeCustomTag('spoiler', (parser, parent) => { + const link = parser.createElement('a'); + const content = parser.createElement('span'); + link.href = '#'; + link.onclick = (e) => { + const target = e.target as HTMLElement; + target.parentElement!.replaceChild(content, target); + return false; + }; + link.appendChild(document.createTextNode('[click to show spoiler]')); + parent.appendChild(link); + return content; + })); } parseEverything(input: string): HTMLElement { @@ -86,4 +99,4 @@ export class CoreBBCodeParser extends BBCodeParser { input = input.replace(findUrlRegex, (match, tag) => tag === undefined ? `[url]${match}[/url]` : match); return super.parseEverything(input); } -} \ No newline at end of file +} diff --git a/bbcode/editor.ts b/bbcode/editor.ts index 279ce55..44d65ba 100644 --- a/bbcode/editor.ts +++ b/bbcode/editor.ts @@ -89,6 +89,12 @@ export let defaultButtons: ReadonlyArray = [ icon: 'fa-smile', key: Keys.KeyE }, + { + title: 'Spoiler (Ctrl+K)\n\nHidden until explicitly clicked by the viewer.', + tag: 'spoiler', + icon: 'fa-eye-slash', + key: Keys.KeyK + }, { title: 'Noparse (Ctrl+N)\n\nAll BBCode placed within this tag will be ignored and treated as text. Great for sharing structure without it being rendered.', tag: 'noparse', diff --git a/bbcode/parser.ts b/bbcode/parser.ts index 6069c98..34ed158 100644 --- a/bbcode/parser.ts +++ b/bbcode/parser.ts @@ -77,7 +77,7 @@ export class BBCodeParser { const parent = document.createElement('span'); parent.className = 'bbcode'; this._currentTag = {tag: '', line: 1, column: 1}; - this.parse(input, 0, undefined, parent, () => true); + this.parse(input, 0, undefined, parent, () => true, 0); //if(process.env.NODE_ENV !== 'production' && this._warnings.length > 0) // console.log(this._warnings); @@ -115,7 +115,7 @@ export class BBCodeParser { } private parse(input: string, start: number, self: BBCodeTag | undefined, parent: HTMLElement | undefined, - isAllowed: (tag: string) => boolean): number { + isAllowed: (tag: string) => boolean, depth: number): number { let currentTag = this._currentTag; const selfAllowed = self !== undefined ? isAllowed(self.tag) : true; if(self !== undefined) { @@ -157,21 +157,21 @@ export class BBCodeParser { parent.appendChild(document.createTextNode(input.substring(mark, allowed ? tagStart : i + 1))); mark = i + 1; } - if(!allowed || parent === undefined) { - i = this.parse(input, i + 1, tag, parent, isAllowed); + if(!allowed || parent === undefined || depth > 100) { + i = this.parse(input, i + 1, tag, parent, isAllowed, depth + 1); mark = i + 1; continue; } let element: HTMLElement | undefined; if(tag instanceof BBCodeTextTag) { - i = this.parse(input, i + 1, tag, undefined, isAllowed); + i = this.parse(input, i + 1, tag, undefined, isAllowed, depth + 1); element = tag.createElement(this, parent, param, input.substring(mark, input.lastIndexOf('[', i))); if(element === undefined) parent.appendChild(document.createTextNode(input.substring(tagStart, i + 1))); } else { element = tag.createElement(this, parent, param, ''); if(element === undefined) parent.appendChild(document.createTextNode(input.substring(tagStart, i + 1))); if(!tag.noClosingTag) - i = this.parse(input, i + 1, tag, element !== undefined ? element : parent, isAllowed); + i = this.parse(input, i + 1, tag, element !== undefined ? element : parent, isAllowed, depth + 1); if(element === undefined) parent.appendChild(document.createTextNode(input.substring(input.lastIndexOf('[', i), i + 1))); } diff --git a/chat/Logs.vue b/chat/Logs.vue index 8b47028..cb8d75b 100644 --- a/chat/Logs.vue +++ b/chat/Logs.vue @@ -23,7 +23,7 @@
+ :placeholder="l('filter')"> @@ -47,7 +47,8 @@ class="fa fa-download">
-
+
@@ -77,8 +78,15 @@ return format(date, 'YYYY-MM-DD'); } - function getLogs(messages: ReadonlyArray): string { - return messages.reduce((acc, x) => acc + messageToString(x, (date) => formatTime(date, true)), ''); + function getLogs(messages: ReadonlyArray, html: boolean): string { + const start = html ? + `` : ''; + return '
' + messages.reduce((acc, x) => acc + messageToString(x, (date) => formatTime(date, true), + html ? (c) => { + const gender = core.characters.get(c).gender; + return `${c}`; + } : undefined, + html ? (t) => `${core.bbCodeParser.parseEverything(t).innerHTML}` : undefined), start) + '
'; } @Component({ @@ -187,16 +195,18 @@ downloadDay(): void { if(this.selectedConversation === undefined || this.selectedDate === undefined || this.messages.length === 0) return; - const name = `${this.selectedConversation.name}-${formatDate(new Date(this.selectedDate))}.txt`; - this.download(name, `data:${encodeURIComponent(name)},${encodeURIComponent(getLogs(this.messages))}`); + const html = confirm(l('logs.html')); + const name = `${this.selectedConversation.name}-${formatDate(new Date(this.selectedDate))}.${html ? 'html' : 'txt'}`; + this.download(name, `data:${encodeURIComponent(name)},${encodeURIComponent(getLogs(this.messages, html))}`); } async downloadConversation(): Promise { if(this.selectedConversation === undefined) return; const zip = new Zip(); + const html = confirm(l('logs.html')); for(const date of this.dates) { const messages = await core.logs.getLogs(this.selectedCharacter, this.selectedConversation.key, date); - zip.addFile(`${formatDate(date)}.txt`, getLogs(messages)); + zip.addFile(`${formatDate(date)}.${html ? 'html' : 'txt'}`, getLogs(messages, html)); } this.download(`${this.selectedConversation.name}.zip`, URL.createObjectURL(zip.build())); } @@ -204,12 +214,13 @@ async downloadCharacter(): Promise { if(this.selectedCharacter === '' || !confirm(l('logs.confirmExport', this.selectedCharacter))) return; const zip = new Zip(); + const html = confirm(l('logs.html')); for(const conv of this.conversations) { zip.addFile(`${conv.name}/`, ''); const dates = await core.logs.getLogDates(this.selectedCharacter, conv.key); for(const date of dates) { const messages = await core.logs.getLogs(this.selectedCharacter, conv.key, date); - zip.addFile(`${conv.name}/${formatDate(date)}.txt`, getLogs(messages)); + zip.addFile(`${conv.name}/${formatDate(date)}.${html ? 'html' : 'txt'}`, getLogs(messages, html)); } } this.download(`${this.selectedCharacter}.zip`, URL.createObjectURL(zip.build())); @@ -272,9 +283,11 @@ if(this.lockScroll) return; if(list === undefined || ev !== undefined && Math.abs(list.scrollTop - this.lastScroll) < 50) return; this.lockScroll = true; + function getTop(index: number): number { return (list!.children[index]).offsetTop; } + while(this.selectedConversation !== undefined && this.selectedDate === undefined && this.dialog.isShown) { const oldHeight = list.scrollHeight, oldTop = list.scrollTop; const oldFirst = this.displayedMessages[0]; @@ -325,4 +338,4 @@ display: flex; flex-direction: column; } - \ No newline at end of file + diff --git a/chat/common.ts b/chat/common.ts index 851056c..21e2c99 100644 --- a/chat/common.ts +++ b/chat/common.ts @@ -61,12 +61,14 @@ export function formatTime(this: void | never, date: Date, noDate: boolean = fal return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`; } -export function messageToString(this: void | never, msg: Conversation.Message, timeFormatter: (date: Date) => string = formatTime): string { +export function messageToString(this: void | never, msg: Conversation.Message, timeFormatter: (date: Date) => string = formatTime, + characterTransform: (str: string) => string = (x) => x, + textTransform: (str: string) => string = (x) => x): string { let text = `[${timeFormatter(msg.time)}] `; if(msg.type !== Conversation.Message.Type.Event) - text += (msg.type === Conversation.Message.Type.Action ? '*' : '') + msg.sender.name + + text += (msg.type === Conversation.Message.Type.Action ? '*' : '') + characterTransform(msg.sender.name) + (msg.type === Conversation.Message.Type.Message ? ':' : ''); - return `${text} ${msg.text}\r\n`; + return `${text} ${textTransform(msg.text)}\r\n`; } export function getKey(e: KeyboardEvent): Keys { @@ -98,4 +100,4 @@ export class EventMessage implements Conversation.EventMessage { constructor(readonly text: string, readonly time: Date = new Date()) { } -} \ No newline at end of file +} diff --git a/chat/core.ts b/chat/core.ts index da1fdb8..d6b8aef 100644 --- a/chat/core.ts +++ b/chat/core.ts @@ -44,12 +44,6 @@ const vue = new Vue({ characters: undefined, conversations: undefined, state - }, - watch: { - 'state.hiddenUsers': async(newValue: string[], oldValue: string[]) => { - if(data.settingsStore !== undefined && newValue !== oldValue) - await data.settingsStore.set('hiddenUsers', newValue); - } } }); @@ -86,6 +80,9 @@ export function init(this: void, connection: Connection, logsClass: new() => Log data.register('characters', Characters(connection)); data.register('channels', Channels(connection, core.characters)); data.register('conversations', Conversations()); + data.watch(() => state.hiddenUsers, async(newValue) => { + if(data.settingsStore !== undefined) await data.settingsStore.set('hiddenUsers', newValue); + }); connection.onEvent('connecting', async() => { await data.reloadSettings(); data.bbCodeParser = createBBCodeParser(); diff --git a/chat/localize.ts b/chat/localize.ts index ac8773f..656cbf7 100644 --- a/chat/localize.ts +++ b/chat/localize.ts @@ -92,6 +92,7 @@ const strings: {[key: string]: string | undefined} = { 'logs.corruption.mobile.success': 'Your logs have been fixed.', 'logs.corruption.mobile.error': 'Unable to fix corrupted logs. Please clear the application data or reinstall the app.', 'logs.corruption.web': 'Error reading logs from browser storage. If this issue persists, please clear your stored browser data for F-Chat.', + 'logs.html': 'Would you like to export these logs as HTML with formatting? Otherwise, they will be exported as plain text.', 'user.profile': 'Profile', 'user.message': 'Open conversation', 'user.messageJump': 'View conversation', @@ -430,4 +431,4 @@ export default function l(key: string, ...args: (string | number)[]): string { while(i-- > 0) str = str.replace(new RegExp(`\\{${i}\\}`, 'igm'), args[i].toString()); return str; -} \ No newline at end of file +} diff --git a/electron/Index.vue b/electron/Index.vue index c8ecb87..2b88aec 100644 --- a/electron/Index.vue +++ b/electron/Index.vue @@ -256,7 +256,7 @@ get styling(): string { try { - return ``; + return ``; } catch(e) { if((e).code === 'ENOENT' && this.settings.theme !== 'default') { this.settings.theme = 'default'; @@ -281,4 +281,4 @@ -webkit-user-drag: none; -webkit-app-region: no-drag; } - \ No newline at end of file + diff --git a/electron/pack.js b/electron/pack.js index dc91ac4..65317cf 100644 --- a/electron/pack.js +++ b/electron/pack.js @@ -93,7 +93,7 @@ require('electron-packager')({ const args = [appPaths[0], 'fchat.AppImage', '-u', 'zsync|https://client.f-list.net/fchat.AppImage.zsync']; if(process.argv.length > 2) args.push('-s', '--sign-key', process.argv[2]); else console.warn('Warning: Creating unsigned AppImage'); - if(process.argv.length > 3) args.push('--sign-args', `--no-tty --passphrase=${process.argv[3]}`); + if(process.argv.length > 3) args.push('--sign-args', `--no-tty --pinentry-mode loopback --yes --passphrase=${process.argv[3]}`); fs.chmodSync(downloaded, 0o755); child_process.spawn(downloaded, ['--appimage-extract'], {cwd: distDir}).on('close', () => { const child = child_process.spawn(path.join(distDir, 'squashfs-root', 'AppRun'), args, {cwd: distDir, env: {ARCH: 'x86_64'}}); @@ -103,4 +103,4 @@ require('electron-packager')({ }); }, (e) => console.error(`HTTP error: ${e.message}`)); } -}, (e) => console.log(`Error while packaging: ${e.message}`)); \ No newline at end of file +}, (e) => console.log(`Error while packaging: ${e.message}`)); diff --git a/electron/package.json b/electron/package.json index 5228424..3f925ea 100644 --- a/electron/package.json +++ b/electron/package.json @@ -1,6 +1,6 @@ { "name": "fchat", - "version": "3.0.13", + "version": "3.0.16", "author": "The F-List Team", "description": "F-List.net Chat Client", "main": "main.js", diff --git a/mobile/Index.vue b/mobile/Index.vue index 5c679d7..3296194 100644 --- a/mobile/Index.vue +++ b/mobile/Index.vue @@ -127,7 +127,7 @@ get styling(): string { if(window.NativeView !== undefined) window.NativeView.setTheme(this.settings.theme); //tslint:disable-next-line:no-require-imports - return ``; + return ``; } async login(): Promise { diff --git a/mobile/android/.idea/misc.xml b/mobile/android/.idea/misc.xml index 0d45e8d..5c02780 100644 --- a/mobile/android/.idea/misc.xml +++ b/mobile/android/.idea/misc.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/mobile/android/.idea/modules.xml b/mobile/android/.idea/modules.xml index 816cb5f..09b6987 100644 --- a/mobile/android/.idea/modules.xml +++ b/mobile/android/.idea/modules.xml @@ -2,8 +2,8 @@ - - + + \ No newline at end of file diff --git a/mobile/android/app/build.gradle b/mobile/android/app/build.gradle index dee09bc..cab42af 100644 --- a/mobile/android/app/build.gradle +++ b/mobile/android/app/build.gradle @@ -3,13 +3,13 @@ apply plugin: 'kotlin-android' android { compileSdkVersion 28 - buildToolsVersion "28.0.3" + buildToolsVersion "29.0.3" defaultConfig { applicationId "net.f_list.fchat" minSdkVersion 21 targetSdkVersion 27 - versionCode 25 - versionName "3.0.12" + versionCode 28 + versionName "3.0.16" } buildTypes { release { diff --git a/mobile/android/build.gradle b/mobile/android/build.gradle index 3b4d423..39ee91e 100644 --- a/mobile/android/build.gradle +++ b/mobile/android/build.gradle @@ -1,13 +1,13 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.2.30' + ext.kotlin_version = '1.3.60' repositories { jcenter() google() } dependencies { - classpath 'com.android.tools.build:gradle:3.1.3' + classpath 'com.android.tools.build:gradle:3.5.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong diff --git a/mobile/android/gradle/wrapper/gradle-wrapper.properties b/mobile/android/gradle/wrapper/gradle-wrapper.properties index ea720f9..1b16c34 100644 --- a/mobile/android/gradle/wrapper/gradle-wrapper.properties +++ b/mobile/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-bin.zip diff --git a/mobile/ios/F-Chat.xcodeproj/project.pbxproj b/mobile/ios/F-Chat.xcodeproj/project.pbxproj index 4731c87..e5eadb5 100644 --- a/mobile/ios/F-Chat.xcodeproj/project.pbxproj +++ b/mobile/ios/F-Chat.xcodeproj/project.pbxproj @@ -112,11 +112,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 0920; + LastUpgradeCheck = 1130; ORGANIZATIONNAME = "F-List"; TargetAttributes = { 6CA94BA71FEFEE7800183A1A = { CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1130; ProvisioningStyle = Automatic; SystemCapabilities = { com.apple.BackgroundModes = { @@ -218,6 +219,7 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; @@ -225,6 +227,7 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -275,6 +278,7 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; @@ -282,6 +286,7 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -321,7 +326,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "net.f-list.F-Chat"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -336,7 +341,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "net.f-list.F-Chat"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; diff --git a/mobile/ios/F-Chat/AppDelegate.swift b/mobile/ios/F-Chat/AppDelegate.swift index ecede7f..3bb5f31 100644 --- a/mobile/ios/F-Chat/AppDelegate.swift +++ b/mobile/ios/F-Chat/AppDelegate.swift @@ -2,11 +2,9 @@ import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { - var window: UIWindow? - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true } @@ -32,7 +30,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func applicationWillTerminate(_ application: UIApplication) { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } - - } - diff --git a/mobile/ios/F-Chat/Background.swift b/mobile/ios/F-Chat/Background.swift index 790a12a..be53fe7 100644 --- a/mobile/ios/F-Chat/Background.swift +++ b/mobile/ios/F-Chat/Background.swift @@ -7,7 +7,7 @@ class Background: NSObject, WKScriptMessageHandler { override init() { let session = AVAudioSession.sharedInstance(); - try! session.setCategory(AVAudioSessionCategoryPlayback, with: .mixWithOthers) + try! session.setCategory(AVAudioSession.Category.playback, options: .mixWithOthers) player.volume = 0 player.numberOfLoops = -1; player.play() diff --git a/mobile/ios/F-Chat/Notification.swift b/mobile/ios/F-Chat/Notification.swift index 903baf1..f1332c1 100644 --- a/mobile/ios/F-Chat/Notification.swift +++ b/mobile/ios/F-Chat/Notification.swift @@ -7,7 +7,7 @@ class Notification: NSObject, WKScriptMessageHandler, UNUserNotificationCenterDe let center = UNUserNotificationCenter.current() let baseDir = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first! var webView: WKWebView! - + func userContentController(_ controller: WKUserContentController, didReceive message: WKScriptMessage) { center.delegate = self self.webView = message.webView @@ -29,14 +29,14 @@ class Notification: NSObject, WKScriptMessageHandler, UNUserNotificationCenterDe return } } - + func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { if(response.actionIdentifier == UNNotificationDefaultActionIdentifier) { webView.evaluateJavaScript("document.dispatchEvent(new CustomEvent('notification-clicked',{detail:{data:'\(response.notification.request.content.userInfo["data"]!)'}}))") } completionHandler() } - + func notify(_ notify: Bool, _ title: String, _ text: String, _ icon: String, _ sound: String?, _ data: String, _ cb: (String?) -> Void) { if(!notify) { if(sound != nil) { @@ -49,14 +49,14 @@ class Notification: NSObject, WKScriptMessageHandler, UNUserNotificationCenterDe let content = UNMutableNotificationContent() content.title = title if(sound != nil) { - content.sound = UNNotificationSound(named: Bundle.main.path(forResource: "www/sounds/" + sound!, ofType: "wav")!) + content.sound = UNNotificationSound(named: UNNotificationSoundName(Bundle.main.path(forResource: "www/sounds/" + sound!, ofType: "wav")!)) } content.body = text content.userInfo["data"] = data center.add(UNNotificationRequest(identifier: "1", content: content, trigger: UNTimeIntervalNotificationTrigger.init(timeInterval: 1, repeats: false))) cb("1"); } - + func requestPermission(_ cb: @escaping (String?) -> Void) { center.requestAuthorization(options: [.alert, .sound]) { (_, _) in cb(nil) diff --git a/mobile/ios/F-Chat/ViewController.swift b/mobile/ios/F-Chat/ViewController.swift index 9c57407..197d518 100644 --- a/mobile/ios/F-Chat/ViewController.swift +++ b/mobile/ios/F-Chat/ViewController.swift @@ -29,13 +29,12 @@ class ViewController: UIViewController, WKNavigationDelegate, WKUIDelegate { webView.uiDelegate = self webView.navigationDelegate = self view = webView - NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardDidShow), name: NSNotification.Name.UIKeyboardDidShow, object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardDidShow), name: UIResponder.keyboardDidShowNotification, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil) webView.scrollView.contentInsetAdjustmentBehavior = .never webView.scrollView.bounces = false UIApplication.shared.statusBarStyle = .lightContent - (UIApplication.shared.value(forKey: "statusBar") as! UIView).backgroundColor = UIColor(white: 0, alpha: 0.5) } override func viewDidLoad() { @@ -47,8 +46,8 @@ class ViewController: UIViewController, WKNavigationDelegate, WKUIDelegate { @objc func keyboardWillShow(notification: NSNotification) { let info = notification.userInfo! - let newHeight = view.window!.frame.height - (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.height - UIView.animate(withDuration: (info[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue, animations: { + let newHeight = view.window!.frame.height - (info[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.height + UIView.animate(withDuration: (info[UIResponder.keyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue, animations: { self.webView.frame = CGRect(x: 0, y: 0, width: self.webView.frame.width, height: newHeight) }) } @@ -59,7 +58,7 @@ class ViewController: UIViewController, WKNavigationDelegate, WKUIDelegate { @objc func keyboardWillHide(notification: NSNotification) { let info = notification.userInfo! - UIView.animate(withDuration: (info[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue, animations: { + UIView.animate(withDuration: (info[UIResponder.keyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue, animations: { self.webView.frame = UIApplication.shared.windows[0].frame }) } @@ -88,7 +87,7 @@ class ViewController: UIViewController, WKNavigationDelegate, WKUIDelegate { decisionHandler(.cancel) let str = url.absoluteString if(url.scheme == "data") { - let start = str.index(of: ",")! + let start = str.firstIndex(of: ",")! let file = FileManager.default.temporaryDirectory.appendingPathComponent(str[str.index(str.startIndex, offsetBy: 5).. { return l('chat.confirmLeave'); }); -require(`../scss/themes/chat/${chatSettings.theme}.scss`); +require(`!style-loader?{"attrs":{"id":"themeStyle"}}!css-loader!sass-loader!../scss/themes/chat/${chatSettings.theme}.scss`); new Chat({ //tslint:disable-line:no-unused-expression el: '#app', propsData: {ownCharacters: chatSettings.characters, defaultCharacter: chatSettings.defaultCharacter, version} -}); \ No newline at end of file +}); diff --git a/webchat/package.json b/webchat/package.json index 1d2dee2..546774f 100644 --- a/webchat/package.json +++ b/webchat/package.json @@ -1,6 +1,6 @@ { "name": "net.f_list.fchat", - "version": "3.0.12", + "version": "3.0.16", "displayName": "F-Chat", "author": "The F-List Team", "description": "F-List.net Chat Client", @@ -11,4 +11,4 @@ "build:dist": "node ../webpack production", "watch": "node ../webpack watch" } -} \ No newline at end of file +} diff --git a/webchat/webpack.config.js b/webchat/webpack.config.js index e4e7676..6e0a9d2 100644 --- a/webchat/webpack.config.js +++ b/webchat/webpack.config.js @@ -36,8 +36,8 @@ const config = { {test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'file-loader'}, {test: /\.(wav|mp3|ogg)$/, loader: 'file-loader?name=sounds/[name].[ext]'}, {test: /\.(png|html)$/, loader: 'file-loader?name=[name].[ext]'}, - {test: /\.scss/, use: ['vue-style-loader', 'css-loader', 'sass-loader']}, - {test: /\.css/, use: ['vue-style-loader', 'css-loader']} + {test: /\.scss$/, use: ['vue-style-loader', 'css-loader', 'sass-loader']}, + {test: /\.css$/, use: ['vue-style-loader', 'css-loader']}, ] }, plugins: [