Add push notification extensions (#4005)
* add wav * add sound to config * add extension to `updateExtensions.sh` * add ios source files * add a build extension * add a new module * use correct type on ios * update the build plugin * add android handler * create a patch for expo-notifications * basic android implementation * add entitlements for notifications extension * add some generic logic for ios * add age check logic * add extension to app config * remove dash * move directory * rename again * update privacy manifest * add prefs storage ios * better types * create interface for setting and getting prefs * add notifications prefs for android * add functions to module * add types to js * add prefs context * add web stub * wrap the app * fix types * more preferences for ios * add a test toggle * swap vars * update patch * fix patch error * fix typo * sigh * sigh * get stored prefs on launch * anotehr type * simplify * about finished * comment * adjust plugin * use supported file types * update NSE * futureproof ios * futureproof android * update sound file name * handle initialization * more cleanup * update js types * strict js types * set the notification channel * rm * add silent channel * add mute logic * update patch * podfile * adjust channels * fix android channel * update readme * oreo or higher * nit * don't use getValue * nit
This commit is contained in:
parent
31868b255f
commit
bf7b66d5c1
38 changed files with 1297 additions and 12 deletions
|
@ -0,0 +1,21 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = 'ExpoBackgroundNotificationHandler'
|
||||
s.version = '1.0.0'
|
||||
s.summary = 'Interface for BlueskyNSE preferences'
|
||||
s.description = 'Interface for BlueskyNSE preferenes'
|
||||
s.author = ''
|
||||
s.homepage = 'https://github.com/bluesky-social/social-app'
|
||||
s.platforms = { :ios => '13.4', :tvos => '13.4' }
|
||||
s.source = { git: '' }
|
||||
s.static_framework = true
|
||||
|
||||
s.dependency 'ExpoModulesCore'
|
||||
|
||||
# Swift/Objective-C compatibility
|
||||
s.pod_target_xcconfig = {
|
||||
'DEFINES_MODULE' => 'YES',
|
||||
'SWIFT_COMPILATION_MODE' => 'wholemodule'
|
||||
}
|
||||
|
||||
s.source_files = "**/*.{h,m,mm,swift,hpp,cpp}"
|
||||
end
|
|
@ -0,0 +1,116 @@
|
|||
import ExpoModulesCore
|
||||
|
||||
let APP_GROUP = "group.app.bsky"
|
||||
|
||||
let DEFAULTS: [String:Any] = [
|
||||
"playSoundChat" : true,
|
||||
"playSoundFollow": false,
|
||||
"playSoundLike": false,
|
||||
"playSoundMention": false,
|
||||
"playSoundQuote": false,
|
||||
"playSoundReply": false,
|
||||
"playSoundRepost": false,
|
||||
"mutedThreads": [:] as! [String:[String]]
|
||||
]
|
||||
|
||||
/*
|
||||
* The purpose of this module is to store values that are needed by the notification service
|
||||
* extension. Since we would rather get and store values such as age or user mute state
|
||||
* while the app is foregrounded, we should use this module liberally. We should aim to keep
|
||||
* background fetches to a minimum (two or three times per hour) while the app is backgrounded
|
||||
* or killed
|
||||
*/
|
||||
public class ExpoBackgroundNotificationHandlerModule: Module {
|
||||
let userDefaults = UserDefaults(suiteName: APP_GROUP)
|
||||
|
||||
public func definition() -> ModuleDefinition {
|
||||
Name("ExpoBackgroundNotificationHandler")
|
||||
|
||||
OnCreate {
|
||||
DEFAULTS.forEach { p in
|
||||
if userDefaults?.value(forKey: p.key) == nil {
|
||||
userDefaults?.setValue(p.value, forKey: p.key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AsyncFunction("getAllPrefsAsync") { () -> [String:Any]? in
|
||||
var keys: [String] = []
|
||||
DEFAULTS.forEach { p in
|
||||
keys.append(p.key)
|
||||
}
|
||||
return userDefaults?.dictionaryWithValues(forKeys: keys)
|
||||
}
|
||||
|
||||
AsyncFunction("getBoolAsync") { (forKey: String) -> Bool in
|
||||
if let pref = userDefaults?.bool(forKey: forKey) {
|
||||
return pref
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
AsyncFunction("getStringAsync") { (forKey: String) -> String? in
|
||||
if let pref = userDefaults?.string(forKey: forKey) {
|
||||
return pref
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
AsyncFunction("getStringArrayAsync") { (forKey: String) -> [String]? in
|
||||
if let pref = userDefaults?.stringArray(forKey: forKey) {
|
||||
return pref
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
AsyncFunction("setBoolAsync") { (forKey: String, value: Bool) -> Void in
|
||||
userDefaults?.setValue(value, forKey: forKey)
|
||||
}
|
||||
|
||||
AsyncFunction("setStringAsync") { (forKey: String, value: String) -> Void in
|
||||
userDefaults?.setValue(value, forKey: forKey)
|
||||
}
|
||||
|
||||
AsyncFunction("setStringArrayAsync") { (forKey: String, value: [String]) -> Void in
|
||||
userDefaults?.setValue(value, forKey: forKey)
|
||||
}
|
||||
|
||||
AsyncFunction("addToStringArrayAsync") { (forKey: String, string: String) in
|
||||
if var curr = userDefaults?.stringArray(forKey: forKey),
|
||||
!curr.contains(string)
|
||||
{
|
||||
curr.append(string)
|
||||
userDefaults?.setValue(curr, forKey: forKey)
|
||||
}
|
||||
}
|
||||
|
||||
AsyncFunction("removeFromStringArrayAsync") { (forKey: String, string: String) in
|
||||
if var curr = userDefaults?.stringArray(forKey: forKey) {
|
||||
curr.removeAll { s in
|
||||
return s == string
|
||||
}
|
||||
userDefaults?.setValue(curr, forKey: forKey)
|
||||
}
|
||||
}
|
||||
|
||||
AsyncFunction("addManyToStringArrayAsync") { (forKey: String, strings: [String]) in
|
||||
if var curr = userDefaults?.stringArray(forKey: forKey) {
|
||||
strings.forEach { s in
|
||||
if !curr.contains(s) {
|
||||
curr.append(s)
|
||||
}
|
||||
}
|
||||
userDefaults?.setValue(curr, forKey: forKey)
|
||||
}
|
||||
}
|
||||
|
||||
AsyncFunction("removeManyFromStringArrayAsync") { (forKey: String, strings: [String]) in
|
||||
if var curr = userDefaults?.stringArray(forKey: forKey) {
|
||||
strings.forEach { s in
|
||||
curr.removeAll(where: { $0 == s })
|
||||
}
|
||||
userDefaults?.setValue(curr, forKey: forKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue