Skip to content

Commit 99015c5

Browse files
authored
fix: Initialize animatedOnlineCount when view appears with stats (#58)
* fix: Initialize animatedOnlineCount when view appears with stats Problem: - In v1.1.4, online count always shows as 0 - animatedOnlineCount is initialized to 0 as default - When onlineStats changes from nil to a value, animatedOnlineCount stays at 0 - onChange only triggers when the value changes, not on initial load Solution: - Add onAppear to initialize animatedOnlineCount from stats.onlineCount - Check if animatedOnlineCount is 0 and stats has valid count - This ensures the count displays correctly on first load Fixes the regression introduced in PR #57 where animated count feature broke the initial display of online user count. * chore: Change default TestFlight release to internal testing - Set distribute_external to false (internal testing only) - Remove public beta groups and external tester notifications - Skip beta review submission for internal builds - Update workflow and lane descriptions - Simplify upload_to_testflight parameters This allows faster iteration and testing without requiring Beta App Review approval for each build. Public beta releases can still be done manually through App Store Connect when needed. * feat: Add configurable release channel parameter - Add 'release_channel' workflow input (internal/public_beta) - Default to 'internal' for automatic releases - Support 'public_beta' for manual workflow_dispatch - Fastlane beta lane now accepts channel parameter - Dynamically configure TestFlight distribution based on channel: - internal: No beta review, internal testers only - public_beta: Submit for beta review, notify external testers - Update GitHub Release notes to reflect selected channel - Update notification messages based on channel Usage: - Automatic (push to main): Uses 'internal' by default - Manual workflow: Can select 'public_beta' in workflow dispatch UI - Local fastlane: fastlane beta channel:public_beta
1 parent 5a207d5 commit 99015c5

File tree

3 files changed

+89
-47
lines changed

3 files changed

+89
-47
lines changed

.github/workflows/release.yml

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@ on:
1313
required: false
1414
default: false
1515
type: boolean
16+
release_channel:
17+
description: 'TestFlight release channel'
18+
required: false
19+
default: 'internal'
20+
type: choice
21+
options:
22+
- internal
23+
- public_beta
1624

1725
env:
1826
DEVELOPER_DIR: /Applications/Xcode.app/Contents/Developer
@@ -85,7 +93,7 @@ jobs:
8593
echo "✅ Successfully created tag: $TAG_NAME"
8694
8795
build-and-release:
88-
name: Build and Release to TestFlight (Public Beta)
96+
name: Build and Release to TestFlight (Internal Testing)
8997
needs: version-check
9098
if: needs.version-check.outputs.should_release == 'true'
9199
runs-on: macos-latest
@@ -283,6 +291,7 @@ jobs:
283291
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
284292
MATCH_GIT_URL: ${{ secrets.MATCH_GIT_URL }}
285293
TEAM_ID: ${{ secrets.TEAM_ID }}
294+
RELEASE_CHANNEL: ${{ github.event.inputs.release_channel || 'internal' }}
286295
run: |
287296
# Enable verbose output for debugging
288297
export FASTLANE_VERBOSE=true
@@ -291,21 +300,26 @@ jobs:
291300
export LC_ALL=en_US.UTF-8
292301
export LANG=en_US.UTF-8
293302
294-
# Run the beta lane (includes waiting for processing and public beta distribution)
295-
fastlane beta
303+
# Run the beta lane with release channel parameter
304+
# Default to 'internal' for automatic releases (push to main)
305+
# Can be set to 'public_beta' for manual workflow_dispatch
306+
fastlane beta channel:$RELEASE_CHANNEL
296307
297308
- name: Create GitHub Release
298309
uses: softprops/action-gh-release@v1
310+
env:
311+
RELEASE_CHANNEL: ${{ github.event.inputs.release_channel || 'internal' }}
299312
with:
300313
tag_name: ${{ needs.version-check.outputs.new_tag }}
301314
name: Release ${{ needs.version-check.outputs.version }}
302315
body: |
303316
## 🚀 Version ${{ needs.version-check.outputs.version }}
304317
Build: ${{ needs.version-check.outputs.build }}
305318
306-
### TestFlight Public Beta
307-
This version has been automatically submitted to TestFlight for public beta testing.
308-
External testers will receive email notifications when the build is available.
319+
### TestFlight Distribution
320+
**Channel**: ${{ github.event.inputs.release_channel || 'internal' }}
321+
322+
${{ github.event.inputs.release_channel == 'public_beta' && '📧 **Public Beta**: This build has been submitted to TestFlight for public beta testing. External testers will receive email notifications when the build is available after beta review approval.' || '👥 **Internal Testing**: This build is available to internal testers immediately after processing. No beta review required.' }}
309323
310324
### What's New
311325
- See [commit history](https://github.com/${{ github.repository }}/commits/${{ needs.version-check.outputs.new_tag }}) for changes
@@ -317,8 +331,16 @@ jobs:
317331

318332
- name: Post release notification
319333
if: success()
334+
env:
335+
RELEASE_CHANNEL: ${{ github.event.inputs.release_channel || 'internal' }}
320336
run: |
321-
echo "✅ Successfully released version ${{ needs.version-check.outputs.version }} to TestFlight Public Beta!"
337+
CHANNEL_DISPLAY=$([ "$RELEASE_CHANNEL" = "public_beta" ] && echo "Public Beta" || echo "Internal Testing")
338+
echo "✅ Successfully released version ${{ needs.version-check.outputs.version }} to TestFlight $CHANNEL_DISPLAY!"
322339
echo "🏷️ Tag: ${{ needs.version-check.outputs.new_tag }}"
323340
echo "🔢 Build: ${{ needs.version-check.outputs.build }}"
324-
echo "📧 External testers will be notified via email"
341+
echo "📦 Channel: $RELEASE_CHANNEL"
342+
if [ "$RELEASE_CHANNEL" = "public_beta" ]; then
343+
echo "📧 External testers will be notified after beta review approval"
344+
else
345+
echo "👥 Internal testers can access the build immediately after processing"
346+
fi

V2er/View/Widget/Updatable/HeadIndicatorView.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ struct HeadIndicatorView: View {
5858
.foregroundColor(.secondaryText)
5959
}
6060
}
61+
.onAppear {
62+
// Initialize animatedOnlineCount when view appears with valid stats
63+
if animatedOnlineCount == 0 && stats.onlineCount > 0 {
64+
animatedOnlineCount = stats.onlineCount
65+
}
66+
}
6167
.onChange(of: stats.onlineCount) { newValue in
6268
withAnimation(.easeInOut(duration: 0.3)) {
6369
animatedOnlineCount = newValue

fastlane/Fastfile

Lines changed: 53 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ platform :ios do
6767
)
6868
end
6969

70-
desc "Distribute existing build to beta testers"
70+
desc "Distribute existing build to internal testers"
7171
lane :distribute_beta do |options|
7272
# Get App Store Connect API key
7373
api_key = get_api_key
@@ -76,38 +76,38 @@ platform :ios do
7676
build_number = options[:build_number]
7777

7878
begin
79-
# Distribute to beta testers
79+
# Distribute to internal testers only
8080
testflight(
8181
api_key: api_key,
8282
app_identifier: "v2er.app",
83-
skip_submission: false,
84-
distribute_external: true, # Distribute to external testers (public beta)
85-
groups: ["Public Beta", "External Testers", "Beta Testers"], # Public beta groups
86-
notify_external_testers: true, # Send email notifications
87-
uses_non_exempt_encryption: false,
88-
submit_beta_review: true, # Automatically submit for Beta review
83+
skip_submission: true, # Skip beta review for internal testing
84+
distribute_external: false, # Internal testing only (not public beta)
8985
wait_for_uploaded_build: true,
90-
beta_app_description: "V2er is an elegant third-party client for V2EX forum",
91-
beta_app_feedback_email: "support@v2er.app",
92-
demo_account_required: false,
93-
beta_app_review_info: {
94-
contact_email: "support@v2er.app",
95-
contact_first_name: "V2er",
96-
contact_last_name: "Support",
97-
contact_phone: "+86 13800138000",
98-
notes: "This is a third-party client app for V2EX forum. No special account needed for testing."
99-
}
86+
uses_non_exempt_encryption: false
10087
)
10188

102-
UI.success("✅ Successfully distributed build to beta testers!")
89+
UI.success("✅ Successfully distributed build to internal testers!")
10390
rescue => e
10491
UI.error("Failed to distribute: #{e.message}")
10592
UI.message("You may need to manually distribute the build in App Store Connect")
10693
end
10794
end
10895

10996
desc "Build and upload to TestFlight"
110-
lane :beta do
97+
desc "Parameters:"
98+
desc " channel: 'internal' (default) or 'public_beta'"
99+
lane :beta do |options|
100+
# Get release channel from options or environment variable
101+
# Default to 'internal' if not specified
102+
channel = options[:channel] || ENV['RELEASE_CHANNEL'] || 'internal'
103+
104+
UI.message("📦 Release channel: #{channel}")
105+
106+
# Validate channel parameter
107+
unless ['internal', 'public_beta'].include?(channel)
108+
UI.user_error!("Invalid channel: #{channel}. Must be 'internal' or 'public_beta'")
109+
end
110+
111111
# Validate that changelog exists for current version
112112
unless ChangelogHelper.validate_changelog_exists
113113
UI.user_error!("Please update CHANGELOG.md with an entry for the current version before releasing!")
@@ -166,31 +166,45 @@ platform :ios do
166166
# Extract changelog for the current version
167167
changelog_content = ChangelogHelper.extract_changelog(current_version)
168168

169-
# Upload to TestFlight
170-
upload_to_testflight(
169+
# Configure TestFlight upload based on release channel
170+
is_public_beta = channel == 'public_beta'
171+
172+
upload_params = {
171173
api_key: api_key,
172-
skip_submission: false,
174+
skip_submission: !is_public_beta, # Skip beta review for internal, submit for public beta
173175
skip_waiting_for_build_processing: false, # Wait for processing before distribution
174176
wait_processing_interval: 30, # Check every 30 seconds
175177
wait_processing_timeout_duration: 900, # Wait up to 15 minutes for processing
176-
distribute_external: true, # Distribute to external testers (public beta)
178+
distribute_external: is_public_beta, # Internal testing by default, external for public beta
177179
distribute_only: false, # Upload and distribute in one action
178-
groups: ["Public Beta", "External Testers", "Beta Testers"], # Public beta groups
179180
changelog: changelog_content, # Use changelog from CHANGELOG.md
180-
notify_external_testers: true, # Send email notifications to external testers
181-
uses_non_exempt_encryption: false, # Required for automatic distribution
182-
submit_beta_review: true, # Automatically submit for Beta review
183-
beta_app_description: "V2er is an elegant third-party client for V2EX forum",
184-
beta_app_feedback_email: "support@v2er.app",
185-
demo_account_required: false, # No demo account required
186-
beta_app_review_info: {
187-
contact_email: "support@v2er.app",
188-
contact_first_name: "V2er",
189-
contact_last_name: "Support",
190-
contact_phone: "+86 13800138000",
191-
notes: "This is a third-party client app for V2EX forum. No special account needed for testing."
192-
}
193-
)
181+
uses_non_exempt_encryption: false # Required export compliance
182+
}
183+
184+
# Add public beta specific parameters
185+
if is_public_beta
186+
upload_params.merge!({
187+
groups: ["Public Beta", "External Testers", "Beta Testers"], # Public beta groups
188+
notify_external_testers: true, # Send email notifications to external testers
189+
submit_beta_review: true, # Automatically submit for Beta review
190+
beta_app_description: "V2er is an elegant third-party client for V2EX forum",
191+
beta_app_feedback_email: "support@v2er.app",
192+
demo_account_required: false, # No demo account required
193+
beta_app_review_info: {
194+
contact_email: "support@v2er.app",
195+
contact_first_name: "V2er",
196+
contact_last_name: "Support",
197+
contact_phone: "+86 13800138000",
198+
notes: "This is a third-party client app for V2EX forum. No special account needed for testing."
199+
}
200+
})
201+
UI.message("📧 Public beta mode: Will notify external testers and submit for beta review")
202+
else
203+
UI.message("👥 Internal testing mode: No beta review submission required")
204+
end
205+
206+
# Upload to TestFlight
207+
upload_to_testflight(upload_params)
194208

195209
# Notify success
196210
notification(

0 commit comments

Comments
 (0)