feat: add live draw feature and clean up docs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
jjbruntonandClaude Opus 4.5 committed 2026-02-01 14:35:16 +00:00
1 parent 520d0a8444
commit 4c18afaeae
63 files changed
+6728 -12854

No files matched your search

@@ -0,0 +1,63 @@
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'maven-publish'
group = 'expo.modules.widgetbridge'
version = '0.0.1'
buildscript {
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
if (expoModulesCorePlugin.exists()) {
apply from: expoModulesCorePlugin
applyKotlinExpoModulesCorePlugin()
}
}
afterEvaluate {
publishing {
publications {
release(MavenPublication) {
from components.release
}
}
repositories {
maven {
url = mavenLocal().url
}
}
}
}
android {
namespace "expo.modules.widgetbridge"
compileSdkVersion safeExtGet("compileSdkVersion", 34)
defaultConfig {
minSdkVersion safeExtGet("minSdkVersion", 23)
targetSdkVersion safeExtGet("targetSdkVersion", 34)
}
publishing {
singleVariant("release") {
withSourcesJar()
}
}
lintOptions {
abortOnError false
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_17.majorVersion
}
}
dependencies {
implementation project(':expo-modules-core')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}"
}
@@ -0,0 +1 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" />
@@ -0,0 +1,48 @@
package expo.modules.widgetbridge
import android.appwidget.AppWidgetManager
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import expo.modules.kotlin.modules.Module
import expo.modules.kotlin.modules.ModuleDefinition
class WidgetBridgeModule : Module() {
override fun definition() = ModuleDefinition {
Name("WidgetBridge")
Function("setWidgetData") { key: String, value: String ->
val ctx = requireNotNull(appContext.reactContext)
ctx.getSharedPreferences("${ctx.packageName}.widgetdata", Context.MODE_PRIVATE)
.edit()
.putString(key, value)
.apply()
}
Function("reloadWidgets") {
val ctx = requireNotNull(appContext.reactContext)
val intent = Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE)
val widgetManager = AppWidgetManager.getInstance(ctx)
val providers = ctx.packageManager.queryBroadcastReceivers(
Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE),
PackageManager.GET_META_DATA
)
for (provider in providers) {
if (provider.activityInfo.packageName == ctx.packageName) {
val component = ComponentName(
provider.activityInfo.packageName,
provider.activityInfo.name
)
val ids = widgetManager.getAppWidgetIds(component)
if (ids.isNotEmpty()) {
val updateIntent = Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE)
updateIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids)
updateIntent.component = component
ctx.sendBroadcast(updateIntent)
}
}
}
}
}
}
@@ -0,0 +1,9 @@
{
"platforms": ["ios", "android"],
"ios": {
"modules": ["WidgetBridgeModule"]
},
"android": {
"modules": ["expo.modules.widgetbridge.WidgetBridgeModule"]
}
}
@@ -0,0 +1,11 @@
import { requireNativeModule } from "expo";
const WidgetBridge = requireNativeModule("WidgetBridge");
export function setWidgetData(key: string, value: string): void {
WidgetBridge.setWidgetData(key, value);
}
export function reloadWidgets(): void {
WidgetBridge.reloadWidgets();
}
@@ -0,0 +1,15 @@
Pod::Spec.new do |s|
s.name = 'WidgetBridge'
s.version = '0.0.1'
s.summary = 'Bridge for writing widget data to shared storage'
s.description = 'Expo module for writing to UserDefaults/SharedPreferences and reloading widgets'
s.author = ''
s.homepage = 'https://github.com/example'
s.platforms = { :ios => '15.1' }
s.source = { git: '' }
s.static_framework = true
s.dependency 'ExpoModulesCore'
s.source_files = '**/*.{h,m,mm,swift,hpp,cpp}'
end
@@ -0,0 +1,19 @@
import ExpoModulesCore
import WidgetKit
public class WidgetBridgeModule: Module {
public func definition() -> ModuleDefinition {
Name("WidgetBridge")
Function("setWidgetData") { (key: String, value: String) in
let suite = UserDefaults(suiteName: "group.com.sauci.app")
suite?.set(value, forKey: key)
}
Function("reloadWidgets") {
if #available(iOS 14.0, *) {
WidgetCenter.shared.reloadAllTimelines()
}
}
}
}