Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
#!/usr/bin/env sh
. "$(dirname "$0")/_/husky.sh"

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"

echo "🔥 HUSKY PRE-COMMIT RUNNING"
npx lint-staged


68 changes: 68 additions & 0 deletions ios-widge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# iOS 위젯 실행 방법 (개발자용)

앱 자체는 Expo로 실행하지만,
iOS 위젯은 반드시 Xcode로 빌드/실행해야 합니다.
(WidgetKit은 네이티브 Extension이라 Expo만으로는 실행되지 않습니다)

사전 준비

- Xcode 설치 (시뮬레이터 포함)
- CocoaPods 설치
- Node / npm 환경 정상 동작

## 1️⃣ JS 의존성 설치

프로젝트 루트에서 실행:

```bash
npm install
```

## 2️⃣ iOS Pods 설치

위젯 및 일부 네이티브 모듈은 CocoaPods에 의존합니다.

```bash
cd ios
pod install --repo-update
cd ..
```

정상 설치 여부 확인:

```bash
test -f ios/Podfile.lock && echo "Podfile.lock OK"
```

## 3️⃣ Expo 번들러 실행

터미널 하나 열어두고 계속 실행 상태로 유지합니다.

```bash
npm run dev
# (expo start -c)
```

## 4️⃣ Xcode에서 iOS 워크스페이스 열기

```bash
open ios/*.xcworkspace
```

## 5️⃣ Xcode에서 앱 1회 실행

Xcode 상단에서:

1. Scheme: RabbitTracker
2. Simulator 기기 선택
3. ▶️ Run

이 단계는 위젯을 시스템에 설치하기 위해 반드시 필요합니다.

## 6️⃣ iOS 시뮬레이터에서 위젯 추가

1. 시뮬레이터 홈 화면 이동
2. 빈 공간 길게 누르기
3. `+` 버튼 → 위젯 추가
4. Rabbit Tracker 검색
5. 원하는 사이즈의 위젯 추가
52 changes: 52 additions & 0 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1768,6 +1768,50 @@ PODS:
- React-utils (= 0.81.5)
- ReactNativeDependencies
- ReactNativeDependencies (0.81.5)
- RNCAsyncStorage (2.2.0):
- hermes-engine
- RCTRequired
- RCTTypeSafety
- React-Core
- React-Core-prebuilt
- React-debug
- React-Fabric
- React-featureflags
- React-graphics
- React-ImageManager
- React-jsi
- React-NativeModulesApple
- React-RCTFabric
- React-renderercss
- React-rendererdebug
- React-utils
- ReactCodegen
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- ReactNativeDependencies
- Yoga
- RNDateTimePicker (8.4.4):
- hermes-engine
- RCTRequired
- RCTTypeSafety
- React-Core
- React-Core-prebuilt
- React-debug
- React-Fabric
- React-featureflags
- React-graphics
- React-ImageManager
- React-jsi
- React-NativeModulesApple
- React-RCTFabric
- React-renderercss
- React-rendererdebug
- React-utils
- ReactCodegen
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- ReactNativeDependencies
- Yoga
- RNReanimated (4.1.6):
- hermes-engine
- RCTRequired
Expand Down Expand Up @@ -2087,6 +2131,8 @@ DEPENDENCIES:
- ReactCodegen (from `build/generated/ios`)
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
- ReactNativeDependencies (from `../node_modules/react-native/third-party-podspecs/ReactNativeDependencies.podspec`)
- "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)"
- "RNDateTimePicker (from `../node_modules/@react-native-community/datetimepicker`)"
- RNReanimated (from `../node_modules/react-native-reanimated`)
- RNScreens (from `../node_modules/react-native-screens`)
- RNSVG (from `../node_modules/react-native-svg`)
Expand Down Expand Up @@ -2251,6 +2297,10 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon"
ReactNativeDependencies:
:podspec: "../node_modules/react-native/third-party-podspecs/ReactNativeDependencies.podspec"
RNCAsyncStorage:
:path: "../node_modules/@react-native-async-storage/async-storage"
RNDateTimePicker:
:path: "../node_modules/@react-native-community/datetimepicker"
RNReanimated:
:path: "../node_modules/react-native-reanimated"
RNScreens:
Expand Down Expand Up @@ -2341,6 +2391,8 @@ SPEC CHECKSUMS:
ReactCodegen: 4c44b74b77fc41ae25b9e2c7e9bd6e2bc772c23f
ReactCommon: e6e232202a447d353e5531f2be82f50f47cbaa9a
ReactNativeDependencies: 71ce9c28beb282aa720ea7b46980fff9669f428a
RNCAsyncStorage: e85a99325df9eb0191a6ee2b2a842644c7eb29f4
RNDateTimePicker: 6fdd63f5d1e0f21faf4cc8674957c52958a7efae
RNReanimated: 43f611f1c85c90e0273df7399bf1536f8e2bd125
RNScreens: dd61bc3a3e6f6901ad833efa411917d44827cf51
RNSVG: 2825ee146e0f6a16221e852299943e4cceef4528
Expand Down
18 changes: 18 additions & 0 deletions ios/RabbitTrackerWidget/AppIntent.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// AppIntent.swift
// RabbitTrackerWidget
//
// Created by 강민재 on 2/2/26.
//

import WidgetKit
import AppIntents

struct ConfigurationAppIntent: WidgetConfigurationIntent {
static var title: LocalizedStringResource { "Configuration" }
static var description: IntentDescription { "This is an example widget." }

// An example configurable parameter.
@Parameter(title: "Favorite Emoji", default: "😃")
var favoriteEmoji: String
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"images" : [
{
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "tinted"
}
],
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
6 changes: 6 additions & 0 deletions ios/RabbitTrackerWidget/Assets.xcassets/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
13 changes: 13 additions & 0 deletions ios/RabbitTrackerWidget/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.widgetkit-extension</string>
</dict>
<key>RCTNewArchEnabled</key>
<true/>
</dict>
</plist>
62 changes: 62 additions & 0 deletions ios/RabbitTrackerWidget/RabbitTrackerWidget.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//
// RabbitTrackerWidget.swift
// RabbitTrackerWidget
//
// Created by 강민재 on 2/2/26.
//

import WidgetKit
import SwiftUI

struct SimpleEntry: TimelineEntry {
let date: Date
}

struct Provider: TimelineProvider {
func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry(date: Date())
}

func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> Void) {
completion(SimpleEntry(date: Date()))
}

func getTimeline(in context: Context, completion: @escaping (Timeline<SimpleEntry>) -> Void) {
let entry = SimpleEntry(date: Date())
let timeline = Timeline(entries: [entry], policy: .never)
completion(timeline)
}
}

struct RabbitTrackerWidgetEntryView: View {
var entry: Provider.Entry

var body: some View {
VStack(spacing: 8) {
Text("🐰 Rabbit Tracker")
.font(.headline)

Text("Widget is alive!")
.font(.caption)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color(.systemBackground))
}
}

struct RabbitTrackerWidget: Widget {
let kind: String = "RabbitTrackerWidget"

var body: some WidgetConfiguration {
StaticConfiguration(kind: kind, provider: Provider()) { entry in
RabbitTrackerWidgetEntryView(entry: entry)
}
.configurationDisplayName("Rabbit Tracker")
.description("습관을 빠르게 확인하는 위젯")
.supportedFamilies([
.systemSmall,
.systemMedium,
.systemLarge
])
}
}
18 changes: 18 additions & 0 deletions ios/RabbitTrackerWidget/RabbitTrackerWidgetBundle.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// RabbitTrackerWidgetBundle.swift
// RabbitTrackerWidget
//
// Created by 강민재 on 2/2/26.
//

import WidgetKit
import SwiftUI

@main
struct RabbitTrackerWidgetBundle: WidgetBundle {
var body: some Widget {
RabbitTrackerWidget()
RabbitTrackerWidgetControl()
RabbitTrackerWidgetLiveActivity()
}
}
Loading