react-native-icon-switcher 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/IconSwitcher.podspec +20 -0
- package/LICENSE +20 -0
- package/README.md +252 -2
- package/android/build.gradle +51 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/com/iconswitcher/IconSwitcher.kt +380 -0
- package/android/src/main/java/com/iconswitcher/IconSwitcherExceptions.kt +24 -0
- package/android/src/main/java/com/iconswitcher/IconSwitcherModule.kt +67 -0
- package/android/src/main/java/com/iconswitcher/IconSwitcherPackage.kt +30 -0
- package/android/src/test/AndroidManifest.xml +39 -0
- package/android/src/test/java/com/iconswitcher/IconSwitcherTest.kt +392 -0
- package/app.plugin.js +1 -0
- package/ios/ISIconSwitcher.h +49 -0
- package/ios/ISIconSwitcher.m +205 -0
- package/ios/IconSwitcher.h +5 -0
- package/ios/IconSwitcher.mm +100 -0
- package/jest/index.d.ts +31 -0
- package/jest/index.js +98 -0
- package/lib/module/NativeIconSwitcher.js +5 -0
- package/lib/module/NativeIconSwitcher.js.map +1 -0
- package/lib/module/config.js +6 -0
- package/lib/module/config.js.map +1 -0
- package/lib/module/errors.js +28 -0
- package/lib/module/errors.js.map +1 -0
- package/lib/module/index.js +69 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/register.js +2 -0
- package/lib/module/register.js.map +1 -0
- package/lib/module/remote/index.js +119 -0
- package/lib/module/remote/index.js.map +1 -0
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/typetests/icon-name.typetest.js +8 -0
- package/lib/module/typetests/icon-name.typetest.js.map +1 -0
- package/lib/module/typetests/types-in-sync.typetest.js +7 -0
- package/lib/module/typetests/types-in-sync.typetest.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/NativeIconSwitcher.d.ts +18 -0
- package/lib/typescript/src/NativeIconSwitcher.d.ts.map +1 -0
- package/lib/typescript/src/config.d.ts +4 -0
- package/lib/typescript/src/config.d.ts.map +1 -0
- package/lib/typescript/src/errors.d.ts +7 -0
- package/lib/typescript/src/errors.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +20 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/register.d.ts +7 -0
- package/lib/typescript/src/register.d.ts.map +1 -0
- package/lib/typescript/src/remote/index.d.ts +17 -0
- package/lib/typescript/src/remote/index.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +59 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/package.json +251 -4
- package/plugin/build/cli.d.ts +3 -0
- package/plugin/build/cli.js +89 -0
- package/plugin/build/core/assets.d.ts +80 -0
- package/plugin/build/core/assets.js +463 -0
- package/plugin/build/core/errors.d.ts +4 -0
- package/plugin/build/core/errors.js +11 -0
- package/plugin/build/core/validate.d.ts +6 -0
- package/plugin/build/core/validate.js +229 -0
- package/plugin/build/index.d.ts +6 -0
- package/plugin/build/index.js +134 -0
- package/plugin/build/load-config.d.ts +3 -0
- package/plugin/build/load-config.js +50 -0
- package/plugin/build/paths.d.ts +15 -0
- package/plugin/build/paths.js +153 -0
- package/plugin/build/sync.d.ts +12 -0
- package/plugin/build/sync.js +162 -0
- package/plugin/build/transforms/android.d.ts +5 -0
- package/plugin/build/transforms/android.js +212 -0
- package/plugin/build/transforms/errors.d.ts +4 -0
- package/plugin/build/transforms/errors.js +11 -0
- package/plugin/build/transforms/index.d.ts +4 -0
- package/plugin/build/transforms/index.js +12 -0
- package/plugin/build/transforms/ios.d.ts +4 -0
- package/plugin/build/transforms/ios.js +111 -0
- package/plugin/build/transforms/sampleConfigs.d.ts +3 -0
- package/plugin/build/transforms/sampleConfigs.js +33 -0
- package/plugin/build/transforms/types.d.ts +2 -0
- package/plugin/build/transforms/types.js +14 -0
- package/plugin/build/types.d.ts +61 -0
- package/plugin/build/types.js +5 -0
- package/src/NativeIconSwitcher.ts +17 -0
- package/src/config.ts +15 -0
- package/src/errors.ts +38 -0
- package/src/index.tsx +78 -0
- package/src/register.ts +4 -0
- package/src/remote/index.ts +142 -0
- package/src/types.ts +59 -0
- package/src/typetests/icon-name.typetest.ts +12 -0
- package/src/typetests/types-in-sync.typetest.ts +16 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = "IconSwitcher"
|
|
7
|
+
s.version = package["version"]
|
|
8
|
+
s.summary = package["description"]
|
|
9
|
+
s.homepage = package["homepage"]
|
|
10
|
+
s.license = package["license"]
|
|
11
|
+
s.authors = package["author"]
|
|
12
|
+
|
|
13
|
+
s.platforms = { :ios => min_ios_version_supported }
|
|
14
|
+
s.source = { :git => "https://github.com/RRigueira/react-native-icon-switcher.git", :tag => "v#{s.version}" }
|
|
15
|
+
|
|
16
|
+
s.source_files = "ios/**/*.{h,m,mm,swift,cpp}"
|
|
17
|
+
s.private_header_files = "ios/**/*.h"
|
|
18
|
+
|
|
19
|
+
install_modules_dependencies(s)
|
|
20
|
+
end
|
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Rui Rigueira
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
in the Software without restriction, including without limitation the rights
|
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
furnished to do so, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,253 @@
|
|
|
1
|
-
#
|
|
1
|
+
# react-native-icon-switcher
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Switch the app icon at runtime on React Native and Expo from one config file, with native wiring generated for you.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/react-native-icon-switcher)
|
|
6
|
+
[](https://www.npmjs.com/package/react-native-icon-switcher)
|
|
7
|
+
[](https://github.com/RRigueira/react-native-icon-switcher/actions/workflows/ci.yml)
|
|
8
|
+
[](https://docs.expo.dev/config-plugins/introduction/)
|
|
9
|
+
[](https://reactnative.dev/docs/the-new-architecture/landing-page)
|
|
10
|
+
|
|
11
|
+
## What it does / doesn't
|
|
12
|
+
|
|
13
|
+
**Does:** bundle alternate launcher icons in your app binary and switch between them at runtime from JavaScript, using one shared config for Expo prebuild and bare React Native (`sync` CLI). Build time generates iOS alternate icon sets, Android `activity-alias` entries, and typed icon names — no hand-editing `Info.plist`, `AndroidManifest.xml`, or Xcode icon build settings.
|
|
14
|
+
|
|
15
|
+
**Doesn't:** download or set icons that are not in the binary; hide Apple's system “You have changed the icon” alert (private API); or run in **Expo Go** (use a development build / prebuild). Remote artwork still has to be baked in at build time — the optional `syncIcon` helper only chooses among bundled names.
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
### Expo
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
npx expo install react-native-icon-switcher
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Add the config plugin in `app.json` / `app.config.ts` (icon paths can live here or in `icon-switcher.config.ts` at the project root — see [Config](#config)):
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
export default {
|
|
29
|
+
expo: {
|
|
30
|
+
plugins: [
|
|
31
|
+
[
|
|
32
|
+
'react-native-icon-switcher',
|
|
33
|
+
{
|
|
34
|
+
icons: {
|
|
35
|
+
halloween: './assets/icons/halloween.png',
|
|
36
|
+
},
|
|
37
|
+
android: { applyOn: 'background' },
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Then run `npx expo prebuild` or use a development build. Expo Go is not supported.
|
|
46
|
+
|
|
47
|
+
### Bare React Native
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
yarn add react-native-icon-switcher
|
|
51
|
+
# or: npm install react-native-icon-switcher
|
|
52
|
+
|
|
53
|
+
cd ios && pod install
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Create `icon-switcher.config.ts` at the project root (see [Config](#config)), then after every config change:
|
|
57
|
+
|
|
58
|
+
```sh
|
|
59
|
+
npx react-native-icon-switcher sync
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Use `npx react-native-icon-switcher sync --check` in CI to fail when generated native files or `icon-switcher.d.ts` are out of date.
|
|
63
|
+
|
|
64
|
+
**No `expo` package is required** for bare apps: this library is a TurboModule with a standalone `sync` CLI. You only need `expo` if you opt into the Expo config plugin workflow.
|
|
65
|
+
|
|
66
|
+
See `example/` (Expo) and `example-bare/` (bare CLI + `sync`) in this repo.
|
|
67
|
+
|
|
68
|
+
## Config
|
|
69
|
+
|
|
70
|
+
Bare apps use `icon-switcher.config.ts` at the project root. Expo apps can pass the same shape as plugin options or point the plugin at a config file.
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
import { defineIcons } from 'react-native-icon-switcher/config';
|
|
74
|
+
|
|
75
|
+
export default defineIcons({
|
|
76
|
+
default: './assets/icons/default.png',
|
|
77
|
+
icons: {
|
|
78
|
+
halloween: './assets/icons/halloween.png',
|
|
79
|
+
midnight: {
|
|
80
|
+
ios: './assets/icons/midnight-ios.png',
|
|
81
|
+
android: {
|
|
82
|
+
foreground: './assets/icons/midnight-fg.png',
|
|
83
|
+
background: '#0B1020',
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
ios: { flattenOn: '#FFFFFF' },
|
|
88
|
+
android: { applyOn: 'background', skipBrands: [] },
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
| Option | Default | Description |
|
|
93
|
+
| --- | --- | --- |
|
|
94
|
+
| `default` | _(unset)_ | Primary icon. Icon names must match `/^[a-z][a-z0-9_]*$/`; `default` is reserved for the primary icon. |
|
|
95
|
+
| `icons` | _(required)_ | Map of alternate name → square PNG path (1024×1024 ideal) or per-platform `IconSpec`. |
|
|
96
|
+
| `ios.flattenOn` | `#FFFFFF` | Background colour when flattening transparent pixels onto the iOS master. |
|
|
97
|
+
| `android.applyOn` | `'background'` | `'background'`: queue PackageManager updates until the app backgrounds (recommended). `'immediate'`: apply during `set()` (can close the visible activity — see [Android guide](docs/guides/android.md)). |
|
|
98
|
+
| `android.skipBrands` | `[]` | Lower-cased `Build.BRAND` values where switching is disabled at runtime (`isSupported` → `false`). |
|
|
99
|
+
|
|
100
|
+
Per-icon `ios` / `android` fields accept a path or structured variants (`IosIconVariants`, `AndroidAdaptiveIcon`) as in `IconSwitcherConfig` (`react-native-icon-switcher/config` types).
|
|
101
|
+
|
|
102
|
+
**Default icon ownership (Expo):** when your Expo config defines `icon` or `android.adaptiveIcon`, Expo owns the default launcher assets and this library does not overwrite `AppIcon.appiconset` or `ic_launcher*`. You may omit `default` in plugin config (recommended). If you set both Expo's icon and `default`, paths must match per platform after resolving to absolute paths — otherwise sync/prebuild fails with a config error. If Expo has no icon fields, set `default` and the plugin writes default assets.
|
|
103
|
+
|
|
104
|
+
**Default icon ownership (bare):** `sync` writes default assets only when `default` is set in the config.
|
|
105
|
+
|
|
106
|
+
Icons with no art for a platform are omitted from that platform's generated outputs.
|
|
107
|
+
|
|
108
|
+
**Android reserved names:** names may not be `round`, `foreground`, `background`, or `monochrome`, nor end in `_round`, `_foreground`, `_background`, or `_monochrome`.
|
|
109
|
+
|
|
110
|
+
## Usage
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
import IconSwitcher, {
|
|
114
|
+
IconSwitcherError,
|
|
115
|
+
type IconName,
|
|
116
|
+
} from 'react-native-icon-switcher';
|
|
117
|
+
|
|
118
|
+
if (IconSwitcher.isSupported) {
|
|
119
|
+
const names = IconSwitcher.list(); // 'default' first, then config order
|
|
120
|
+
const current = await IconSwitcher.getCurrent();
|
|
121
|
+
const { status } = await IconSwitcher.set('halloween' as IconName);
|
|
122
|
+
// status: 'applied' | 'pending'
|
|
123
|
+
await IconSwitcher.reset();
|
|
124
|
+
await IconSwitcher.applyPending(); // Android: flush queued change; iOS: 'none'
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## API reference
|
|
129
|
+
|
|
130
|
+
| Method | Returns | Notes |
|
|
131
|
+
| --- | --- | --- |
|
|
132
|
+
| `IconSwitcher.isSupported` | `boolean` | `false` when the TurboModule is missing (web, Expo Go, unlink) or the device brand is skipped. |
|
|
133
|
+
| `IconSwitcher.list()` | `IconName[]` | Bundled icon names; `default` first. |
|
|
134
|
+
| `IconSwitcher.getCurrent()` | `Promise<IconName>` | |
|
|
135
|
+
| `IconSwitcher.set(name)` | `Promise<{ status: 'applied' \| 'pending' }>` | Android with `applyOn: 'background'` → `pending` until background or `applyPending()`. |
|
|
136
|
+
| `IconSwitcher.reset()` | same as `set('default')` | |
|
|
137
|
+
| `IconSwitcher.applyPending()` | `Promise<{ status: 'applied' \| 'none' }>` | Android: apply queued icon when not in the foreground; iOS: always `{ status: 'none' }`. |
|
|
138
|
+
|
|
139
|
+
Throws `IconSwitcherError` with a `code` field (native rejections are mapped in JS).
|
|
140
|
+
|
|
141
|
+
### Errors (`IconSwitcherError.code`)
|
|
142
|
+
|
|
143
|
+
| JS code | Native code | When |
|
|
144
|
+
| --- | --- | --- |
|
|
145
|
+
| `unsupported` | `ERR_UNSUPPORTED` | Module unavailable or brand skipped |
|
|
146
|
+
| `unknown_icon` | `ERR_UNKNOWN_ICON` | Name not in the bundle (also thrown synchronously from JS if not in `list()`) |
|
|
147
|
+
| `os_rejected` | `ERR_OS_REJECTED` | OS failure or read-back mismatch |
|
|
148
|
+
| `foreground` | `ERR_FOREGROUND` | Android: `applyPending()` while the app is visible |
|
|
149
|
+
|
|
150
|
+
Unknown native codes map to `os_rejected`.
|
|
151
|
+
|
|
152
|
+
### Typed icon names (`icon-switcher.d.ts`)
|
|
153
|
+
|
|
154
|
+
`sync` and the Expo plugin generate `icon-switcher.d.ts` at the project root:
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
import 'react-native-icon-switcher';
|
|
158
|
+
|
|
159
|
+
declare module 'react-native-icon-switcher' {
|
|
160
|
+
interface Register {
|
|
161
|
+
icons: 'default' | 'halloween' | 'midnight';
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Commit this file and reference `IconName` from `react-native-icon-switcher` for autocomplete on `set`, `getCurrent`, and `reset`.
|
|
167
|
+
|
|
168
|
+
### Remote helper (`react-native-icon-switcher/remote`)
|
|
169
|
+
|
|
170
|
+
`syncIcon` fetches a choice from your backend, validates it against `list()`, and calls `set` when needed. It does not download new artwork.
|
|
171
|
+
|
|
172
|
+
```ts
|
|
173
|
+
import { syncIcon } from 'react-native-icon-switcher/remote';
|
|
174
|
+
|
|
175
|
+
const unsubscribe = await syncIcon({
|
|
176
|
+
fetchChoice: async () => {
|
|
177
|
+
const res = await fetch('https://api.example.com/icon');
|
|
178
|
+
return (await res.json()).iconName as string;
|
|
179
|
+
},
|
|
180
|
+
storage: optionalAsyncKeyValue, // default: in-memory
|
|
181
|
+
retryAfterMs: 24 * 60 * 60 * 1000, // skip re-apply after failure
|
|
182
|
+
onError: (err) => console.warn(err),
|
|
183
|
+
});
|
|
184
|
+
// call unsubscribe() to remove iOS AppState listener
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
On **iOS**, the helper runs when the app is `active` and subscribes to `AppState`. On **Android**, it runs once when called (`set` may still return `pending`).
|
|
188
|
+
|
|
189
|
+
## Testing with Jest
|
|
190
|
+
|
|
191
|
+
Ship a CommonJS mock that never loads native code:
|
|
192
|
+
|
|
193
|
+
```ts
|
|
194
|
+
jest.mock(
|
|
195
|
+
'react-native-icon-switcher',
|
|
196
|
+
() => require('react-native-icon-switcher/jest')
|
|
197
|
+
);
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Helpers (see `jest/index.d.ts`):
|
|
201
|
+
|
|
202
|
+
```ts
|
|
203
|
+
import IconSwitcher, {
|
|
204
|
+
IconSwitcherError,
|
|
205
|
+
__setState,
|
|
206
|
+
__reset,
|
|
207
|
+
} from 'react-native-icon-switcher/jest';
|
|
208
|
+
|
|
209
|
+
beforeEach(() => {
|
|
210
|
+
__reset();
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it('applies a pending switch', async () => {
|
|
214
|
+
__setState({
|
|
215
|
+
setImpl: async (name) => {
|
|
216
|
+
__setState({ current: name });
|
|
217
|
+
return { status: 'applied' };
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
await IconSwitcher.set('halloween');
|
|
222
|
+
expect(await IconSwitcher.getCurrent()).toBe('halloween');
|
|
223
|
+
});
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
`__setState(partial)` merges onto defaults (`isSupported: true`, `iconNames: ['default', 'halloween']`, `current: 'default'`). Customize `setImpl` and `applyPendingImpl` for async behaviour.
|
|
227
|
+
|
|
228
|
+
## Platform notes
|
|
229
|
+
|
|
230
|
+
### iOS
|
|
231
|
+
|
|
232
|
+
- Apple shows a system alert when the icon changes. **`set()` resolves only after the user dismisses that alert** — `await IconSwitcher.set()` can take as long as the alert stays on screen (often ~0.5 s after tapping OK).
|
|
233
|
+
- There is no supported way to hide this alert.
|
|
234
|
+
|
|
235
|
+
### Android
|
|
236
|
+
|
|
237
|
+
Deferred apply, task recreation when aliases toggle, the `applyPending()` foreground guard, cold-start behaviour, and launcher shortcuts are documented in [docs/guides/android.md](docs/guides/android.md).
|
|
238
|
+
|
|
239
|
+
Summary: with default `applyOn: 'background'`, `set()` returns `pending` and the launcher updates after the user leaves the app; the process usually survives but the next open may look like a cold start. `applyPending()` in the foreground is refused with `foreground`.
|
|
240
|
+
|
|
241
|
+
## Requirements
|
|
242
|
+
|
|
243
|
+
- **New Architecture (TurboModule) required** — React Native **≥ 0.82** (developed with **0.88**).
|
|
244
|
+
- **Expo SDK ≥ 52** when using the config plugin (optional peer; developed with **SDK 58**).
|
|
245
|
+
- **Expo Go is not supported** — use a development build or bare native project.
|
|
246
|
+
|
|
247
|
+
## Contributing
|
|
248
|
+
|
|
249
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
250
|
+
|
|
251
|
+
## License
|
|
252
|
+
|
|
253
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
ext.IconSwitcher = [
|
|
2
|
+
minSdkVersion: 24,
|
|
3
|
+
compileSdkVersion: 36
|
|
4
|
+
]
|
|
5
|
+
|
|
6
|
+
ext.getExtOrDefault = { prop ->
|
|
7
|
+
if (rootProject.ext.has(prop)) {
|
|
8
|
+
return rootProject.ext.get(prop)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return IconSwitcher[prop]
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
apply plugin: "com.android.library"
|
|
16
|
+
|
|
17
|
+
if (project.extensions.findByName("kotlin") == null) {
|
|
18
|
+
apply plugin: "kotlin-android"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
apply plugin: "com.facebook.react"
|
|
23
|
+
|
|
24
|
+
android {
|
|
25
|
+
namespace "com.iconswitcher"
|
|
26
|
+
|
|
27
|
+
compileSdkVersion getExtOrDefault("compileSdkVersion")
|
|
28
|
+
|
|
29
|
+
defaultConfig {
|
|
30
|
+
minSdkVersion getExtOrDefault("minSdkVersion")
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
compileOptions {
|
|
34
|
+
sourceCompatibility JavaVersion.VERSION_17
|
|
35
|
+
targetCompatibility JavaVersion.VERSION_17
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
testOptions {
|
|
39
|
+
unitTests.includeAndroidResources = true
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
dependencies {
|
|
44
|
+
implementation "com.facebook.react:react-android"
|
|
45
|
+
implementation "androidx.lifecycle:lifecycle-process:2.8.7"
|
|
46
|
+
|
|
47
|
+
testImplementation "androidx.test:core:1.7.0"
|
|
48
|
+
testImplementation "junit:junit:4.13.2"
|
|
49
|
+
testImplementation "io.mockk:mockk:1.13.11"
|
|
50
|
+
testImplementation "org.robolectric:robolectric:4.16"
|
|
51
|
+
}
|