Skip to content

Commit 3209597

Browse files
authored
Merge pull request #98 from Natifishman/feature/all-optimizations
Performance and Architecture Optimization
2 parents 943a8a1 + cbbc29f commit 3209597

File tree

11 files changed

+765
-21
lines changed

11 files changed

+765
-21
lines changed

.gitignore

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,19 @@ app/server/src/main/resources/firebase-service-account.json
9393
/agents/agent_app_polish.md
9494
/agents/agent_improve_code.md
9595
/agents/agent_warnings_fix.md
96+
97+
# Documentation and optimization files
98+
*.md
99+
!README.md
100+
!scripts/README.md
101+
/optimization/
102+
/.claude/
103+
CODE_REVIEW_CHECKLIST.md
104+
PR_INSTRUCTIONS.md
105+
COMMIT_STRATEGY.md
106+
ENTERPRISE_REFACTORING_FINAL_REPORT.md
107+
JAVA_INTEGRATION_CHANGES.md
108+
OPTIMIZATION_GUIDE.md
109+
PROJECT_CHANGES_SUMMARY.md
110+
UI_IMPROVEMENTS_ROADMAP.md
111+
XML_ENTERPRISE_REFACTORING_CHECKLIST.md

app/build.gradle.kts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,10 @@ dependencies {
308308
implementation(libs.google.firebase.storage)
309309
implementation(libs.firebase.firestore)
310310
// Note: Firebase Cloud Messaging intentionally excluded
311+
312+
// Firebase App Check for security
313+
implementation("com.google.firebase:firebase-appcheck-playintegrity:17.1.1")
314+
implementation("com.google.firebase:firebase-appcheck-debug:17.1.1")
311315

312316
// --- Google Services ---
313317
implementation(libs.gms.play.services.auth)

app/src/main/java/com/example/partymaker/PartyApplication.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,13 @@
1414
import com.example.partymaker.data.repository.GroupRepository;
1515
import com.example.partymaker.data.repository.UserRepository;
1616
import com.example.partymaker.utils.infrastructure.system.MemoryManager;
17+
import com.example.partymaker.utils.infrastructure.PerformanceMonitor;
1718
import com.example.partymaker.ui.features.auxiliary.settings.ServerSettingsActivity;
1819
import com.example.partymaker.utils.ui.feedback.NotificationManager;
1920
import com.google.firebase.FirebaseApp;
21+
import com.google.firebase.appcheck.FirebaseAppCheck;
22+
import com.google.firebase.appcheck.playintegrity.PlayIntegrityAppCheckProviderFactory;
23+
import com.google.firebase.appcheck.debug.DebugAppCheckProviderFactory;
2024

2125
/** Application class for PartyMaker. Initializes repositories and other app-wide components. */
2226
public class PartyApplication extends Application {
@@ -28,18 +32,27 @@ public void onCreate() {
2832
super.onCreate();
2933
instance = this;
3034

35+
// Start performance monitoring
36+
PerformanceMonitor.startTiming("Application.onCreate");
37+
PerformanceMonitor.trackMemoryUsage("Application.onCreate.start");
38+
3139
// Apply saved theme preference
3240
ServerSettingsActivity.applyThemeFromPreferences(this);
3341
Log.d(TAG, "Theme preference applied");
3442

3543
// Initialize Firebase
3644
try {
45+
PerformanceMonitor.startTiming("Firebase.init");
3746
FirebaseApp.initializeApp(this);
3847
Log.d(TAG, "Firebase initialized successfully");
48+
49+
// Initialize Firebase App Check for security
50+
initializeAppCheck();
3951

4052
// Initialize Firebase references
4153
DBRef.init();
4254
Log.d(TAG, "Firebase references initialized successfully");
55+
PerformanceMonitor.endTiming("Firebase.init");
4356
} catch (Exception e) {
4457
Log.e(TAG, "Error initializing Firebase", e);
4558
}
@@ -80,6 +93,10 @@ public void onCreate() {
8093
// Log memory info
8194
Log.d(TAG, "Initial memory usage: " + MemoryManager.getDetailedMemoryInfo());
8295

96+
// End application initialization timing
97+
PerformanceMonitor.trackMemoryUsage("Application.onCreate.end");
98+
PerformanceMonitor.endTiming("Application.onCreate");
99+
83100
Log.d(TAG, "Application initialized");
84101
}
85102

@@ -128,6 +145,33 @@ public void onTerminate() {
128145
public static PartyApplication getInstance() {
129146
return instance;
130147
}
148+
149+
/**
150+
* Initializes Firebase App Check for enhanced security.
151+
* Uses Play Integrity for production and Debug provider for testing.
152+
*/
153+
private void initializeAppCheck() {
154+
try {
155+
FirebaseAppCheck firebaseAppCheck = FirebaseAppCheck.getInstance();
156+
157+
if (BuildConfig.DEBUG) {
158+
// Use debug provider for testing
159+
Log.d(TAG, "Initializing App Check with Debug provider");
160+
firebaseAppCheck.installAppCheckProviderFactory(
161+
DebugAppCheckProviderFactory.getInstance());
162+
} else {
163+
// Use Play Integrity for production
164+
Log.d(TAG, "Initializing App Check with Play Integrity provider");
165+
firebaseAppCheck.installAppCheckProviderFactory(
166+
PlayIntegrityAppCheckProviderFactory.getInstance());
167+
}
168+
169+
Log.d(TAG, "Firebase App Check initialized successfully");
170+
} catch (Exception e) {
171+
Log.e(TAG, "Failed to initialize App Check - continuing without it", e);
172+
// App can still function without App Check, but with reduced security
173+
}
174+
}
131175

132176
/**
133177
* Sets up memory monitoring for debug builds.

app/src/main/java/com/example/partymaker/data/local/AppDatabase.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ public void onCreate(@NonNull SupportSQLiteDatabase db) {
6565
super.onCreate(db);
6666
Log.i(TAG, "Database created for the first time");
6767
createCustomIndexes(db);
68+
69+
// Database monitoring is done through static methods
70+
// No initialization needed for DatabaseMonitor
6871
}
6972

7073
@Override
@@ -74,6 +77,9 @@ public void onOpen(@NonNull SupportSQLiteDatabase db) {
7477

7578
enableForeignKeys(db);
7679
optimizeDatabasePerformance(db);
80+
81+
// Log database opening
82+
Log.d(TAG, "Database opened successfully");
7783
}
7884

7985
@Override

app/src/main/java/com/example/partymaker/ui/features/core/MainActivity.java

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,20 @@ public class MainActivity extends BaseActivity {
9494
private String currentSortMode = "date_nearest"; // default sort
9595
private boolean filterPublicOnly = false;
9696
private boolean filterPrivateOnly = false;
97+
98+
// Date format patterns for parsing
99+
private static final java.text.SimpleDateFormat[] DATE_FORMATS = {
100+
new java.text.SimpleDateFormat("dd/MM/yyyy", java.util.Locale.getDefault()),
101+
new java.text.SimpleDateFormat("d/MM/yyyy", java.util.Locale.getDefault()),
102+
new java.text.SimpleDateFormat("dd/M/yyyy", java.util.Locale.getDefault()),
103+
new java.text.SimpleDateFormat("d/M/yyyy", java.util.Locale.getDefault()),
104+
new java.text.SimpleDateFormat("dd/MMMM/yyyy", java.util.Locale.ENGLISH),
105+
new java.text.SimpleDateFormat("d/MMMM/yyyy", java.util.Locale.ENGLISH),
106+
new java.text.SimpleDateFormat("dd/MMM/yyyy", java.util.Locale.ENGLISH),
107+
new java.text.SimpleDateFormat("d/MMM/yyyy", java.util.Locale.ENGLISH)
108+
};
109+
110+
97111
private boolean filterFreeOnly = false;
98112
private boolean filterUpcomingOnly = false;
99113

@@ -821,22 +835,57 @@ private List<Group> sortGroups(List<Group> groups) {
821835

822836
private int compareDates(Group g1, Group g2) {
823837
try {
838+
// Check for null values first
839+
if (g1.getGroupDays() == null || g1.getGroupMonths() == null || g1.getGroupYears() == null ||
840+
g2.getGroupDays() == null || g2.getGroupMonths() == null || g2.getGroupYears() == null) {
841+
return 0;
842+
}
843+
824844
String date1 = g1.getGroupDays() + "/" + g1.getGroupMonths() + "/" + g1.getGroupYears();
825845
String date2 = g2.getGroupDays() + "/" + g2.getGroupMonths() + "/" + g2.getGroupYears();
826846

827-
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("dd/MM/yyyy", java.util.Locale.getDefault());
828-
java.util.Date d1 = sdf.parse(date1);
829-
java.util.Date d2 = sdf.parse(date2);
830-
831-
if (d1 != null && d2 != null) {
832-
return d1.compareTo(d2);
847+
// Check for "null" strings
848+
if (date1.contains("null") || date2.contains("null")) {
849+
return 0;
833850
}
851+
852+
java.util.Date d1 = parseDate(date1);
853+
java.util.Date d2 = parseDate(date2);
854+
855+
if (d1 == null && d2 == null) return 0;
856+
if (d1 == null) return 1;
857+
if (d2 == null) return -1;
858+
859+
return d1.compareTo(d2);
834860
} catch (Exception e) {
835861
Log.w(TAG, "Error comparing dates", e);
836862
}
837863
return 0;
838864
}
839865

866+
/**
867+
* Parse date string with multiple format support
868+
*/
869+
private java.util.Date parseDate(String dateStr) {
870+
if (dateStr == null || dateStr.isEmpty() || dateStr.contains("null")) {
871+
return null;
872+
}
873+
874+
// Try each date format
875+
for (java.text.SimpleDateFormat format : DATE_FORMATS) {
876+
try {
877+
format.setLenient(false);
878+
return format.parse(dateStr);
879+
} catch (java.text.ParseException e) {
880+
// Try next format
881+
}
882+
}
883+
884+
// Log error only once for unparseable dates
885+
Log.w(TAG, "Could not parse date: " + dateStr);
886+
return null;
887+
}
888+
840889
private void showSortFilterDialog() {
841890
android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(this);
842891
View dialogView = getLayoutInflater().inflate(R.layout.dialog_sort_filter, null);

0 commit comments

Comments
 (0)