From 3be48287dbe042e6b7a6c00eb54a7f46fd0df2ea Mon Sep 17 00:00:00 2001 From: Georgy Lebedik Date: Wed, 25 Jun 2025 18:26:31 +0300 Subject: [PATCH 01/32] Fixed some bugs. Starting using API amICreator of event. --- .../activity/EventDispatcherActivity.java | 10 +++------- .../event/activity/EventOnMapActivity.java | 6 +++--- .../event/message/UpdateEventRequest.java | 12 ++++++------ .../context/event/service/EventService.java | 4 ++++ .../tom/meeter/context/event/utils/Utils.java | 7 ++++--- .../meeter/context/network/dto/EventDTO.java | 18 +++++++++--------- .../profile/activity/ProfileActivity.java | 6 +++++- .../context/profile/domain/GMapEvent.java | 12 ++++++++---- .../profile/fragment/GoogleMapsFragment.java | 4 ++-- .../context/user/activity/UserActivity.java | 10 ++++++++-- .../infrastructure/common/CommonHelper.java | 7 +++++++ .../src/main/res/values-en/strings.xml | 1 + .../src/main/res/values-ru-rRU/strings.xml | 1 + AndroidClient/src/main/res/values/strings.xml | 1 + 14 files changed, 62 insertions(+), 37 deletions(-) diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventDispatcherActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventDispatcherActivity.java index f0c9aa1..129aa42 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventDispatcherActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventDispatcherActivity.java @@ -14,9 +14,7 @@ import androidx.appcompat.app.AppCompatActivity; import com.tom.meeter.App; -import com.tom.meeter.context.auth.infrastructure.AuthHelper; import com.tom.meeter.context.event.service.EventService; -import com.tom.meeter.context.network.dto.EventDTO; import com.tom.meeter.context.token.service.TokenService; import com.tom.meeter.infrastructure.common.Globals; import com.tom.meeter.infrastructure.http.ActivityRecreatorOnAuthFailure; @@ -67,15 +65,13 @@ protected void onCreate(Bundle savedInstanceState) { } private void onInit(String token, String eventId) { - //TODO make isCreatedByMe - eventService.getEvent(Globals.getAuthHeader(token), eventId) + eventService.amICreator(Globals.getAuthHeader(token), eventId) .enqueue(new ActivityRecreatorOnAuthFailure<>(this) { @Override - public void onResponse(Call call, Response resp) { + public void onResponse(Call call, Response resp) { super.onResponse(call, resp); if (resp.code() == HttpCodes.OK) { - EventDTO event = resp.body(); - if (AuthHelper.getUserUuid(accountManager).equals(event.getCreatorId())) { + if (resp.body()) { dispatchToProfileEventActivity(EventDispatcherActivity.this, eventId); } else { dispatchToUserEventActivity(EventDispatcherActivity.this, eventId); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventOnMapActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventOnMapActivity.java index b0a704d..ca43d9c 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventOnMapActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventOnMapActivity.java @@ -97,10 +97,10 @@ public void onMapReady(GoogleMap googleMap) { public void onResponse(Call call, Response response) { if (response.code() == HttpCodes.OK) { EventDTO event = response.body(); - Float latitude = event.getLatitude(); - Float longitude = event.getLongitude(); + Double latitude = event.getLatitude(); + Double longitude = event.getLongitude(); if (latitude == null || longitude == null) { - showMessage(EventOnMapActivity.this, "Event location is not set yet."); + showMessage(EventOnMapActivity.this, R.string.event_location_is_not_set_yet); return; } LatLng eventLatLng = new LatLng(latitude, longitude); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/message/UpdateEventRequest.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/message/UpdateEventRequest.java index bf6535c..4b4f7ad 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/message/UpdateEventRequest.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/message/UpdateEventRequest.java @@ -13,8 +13,8 @@ public class UpdateEventRequest { private Optional starting; private Optional ending; private Optional city; - private Optional latitude; - private Optional longitude; + private Optional latitude; + private Optional longitude; @JsonProperty(value = PHOTO_PATH_KEY) private Optional photoPath; @@ -41,11 +41,11 @@ public Optional getCity() { return city; } - public Optional getLatitude() { + public Optional getLatitude() { return latitude; } - public Optional getLongitude() { + public Optional getLongitude() { return longitude; } @@ -73,11 +73,11 @@ public void setCity(String city) { this.city = Optional.ofNullable(city); } - public void setLatitude(Float latitude) { + public void setLatitude(Double latitude) { this.latitude = Optional.ofNullable(latitude); } - public void setLongitude(Float longitude) { + public void setLongitude(Double longitude) { this.longitude = Optional.ofNullable(longitude); } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/service/EventService.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/service/EventService.java index cc3308c..0d21f5a 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/service/EventService.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/service/EventService.java @@ -25,4 +25,8 @@ Call updateEvent( @DELETE("/event/{id}") Call deleteEvent(@Header(AUTH_HEADER) String authHeader, @Path("id") String eventId); + + @GET("/event/{id}/am_i_creator") + Call amICreator(@Header(AUTH_HEADER) String authHeader, @Path("id") String eventId); + } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/utils/Utils.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/utils/Utils.java index b6ca0c2..28bc06a 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/utils/Utils.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/utils/Utils.java @@ -1,6 +1,6 @@ package com.tom.meeter.context.event.utils; -import static com.tom.meeter.infrastructure.common.CommonHelper.getFloatOrNull; +import static com.tom.meeter.infrastructure.common.CommonHelper.getDoubleOrNull; import static com.tom.meeter.infrastructure.common.CommonHelper.getOffsetDateTime; import static com.tom.meeter.infrastructure.common.CommonHelper.getStringOrNull; @@ -12,6 +12,7 @@ import java.util.Objects; public class Utils { + private Utils() { } @@ -39,11 +40,11 @@ public static UpdateEventRequest createUpdateEventRequest( if (!Objects.equals(event.getCity(), eventCityChange)) { req.setCity(eventCityChange); } - Float eventLatitudeChange = getFloatOrNull(binding.latitude.getText()); + Double eventLatitudeChange = getDoubleOrNull(binding.latitude.getText()); if (!Objects.equals(event.getLatitude(), eventLatitudeChange)) { req.setLatitude(eventLatitudeChange); } - Float eventLongitudeChange = getFloatOrNull(binding.longitude.getText()); + Double eventLongitudeChange = getDoubleOrNull(binding.longitude.getText()); if (!Objects.equals(event.getLongitude(), eventLongitudeChange)) { req.setLongitude(eventLongitudeChange); } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/network/dto/EventDTO.java b/AndroidClient/src/main/java/com/tom/meeter/context/network/dto/EventDTO.java index dd71a17..04013e3 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/network/dto/EventDTO.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/network/dto/EventDTO.java @@ -1,6 +1,6 @@ package com.tom.meeter.context.network.dto; -import static com.tom.meeter.infrastructure.common.JsonHelper.getFloatOrNull; +import static com.tom.meeter.infrastructure.common.JsonHelper.getDoubleOrNull; import static com.tom.meeter.infrastructure.common.JsonHelper.getOffsetDateTimeOrNull; import static com.tom.meeter.infrastructure.common.JsonHelper.getStringOrNull; @@ -40,8 +40,8 @@ public class EventDTO { //Nullable private String description; - private Float latitude; - private Float longitude; + private Double latitude; + private Double longitude; private OffsetDateTime starting; private OffsetDateTime ending; private String city; @@ -59,8 +59,8 @@ public static EventDTO encode(JSONObject json) { //Nullable. result.description = getStringOrNull(DESCRIPTION_KEY, json); - result.latitude = getFloatOrNull(LATITUDE_KEY, json); - result.longitude = getFloatOrNull(LONGITUDE_KEY, json); + result.latitude = getDoubleOrNull(LATITUDE_KEY, json); + result.longitude = getDoubleOrNull(LONGITUDE_KEY, json); result.starting = getOffsetDateTimeOrNull(STARTING_KEY, json); result.ending = getOffsetDateTimeOrNull(ENDING_KEY, json); result.photoPath = getStringOrNull(PHOTO_PATH_KEY, json); @@ -75,11 +75,11 @@ public void setName(String name) { this.name = name; } - public void setLatitude(Float latitude) { + public void setLatitude(Double latitude) { this.latitude = latitude; } - public void setLongitude(Float longitude) { + public void setLongitude(Double longitude) { this.longitude = longitude; } @@ -127,11 +127,11 @@ public String getDescription() { return description; } - public Float getLatitude() { + public Double getLatitude() { return latitude; } - public Float getLongitude() { + public Double getLongitude() { return longitude; } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/ProfileActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/ProfileActivity.java index 42478b6..9d9b415 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/ProfileActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/ProfileActivity.java @@ -49,6 +49,7 @@ import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem; import com.tom.meeter.App; import com.tom.meeter.R; +import com.tom.meeter.context.auth.activity.LoginActivity; import com.tom.meeter.context.network.service.SocketIOService; import com.tom.meeter.context.profile.fragment.CreateNewEventFragment; import com.tom.meeter.context.profile.fragment.EventsFragment; @@ -394,7 +395,10 @@ private void handleLogout() { acc, this, future -> { Log.d(TAG, "Account '" + acc.name + "' removed."); unbindSocketService(); - finishAndRemoveTask(); + Intent intent = new Intent(this, LoginActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + startActivity(intent); + finish(); }, null); } } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/domain/GMapEvent.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/domain/GMapEvent.java index 7cde618..4af1f6a 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/domain/GMapEvent.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/domain/GMapEvent.java @@ -41,11 +41,11 @@ public String getId() { return event.getId(); } - public double getLatitude() { + public Double getLatitude() { return event.getLatitude(); } - public double getLongitude() { + public Double getLongitude() { return event.getLongitude(); } @@ -58,10 +58,14 @@ public void updateName(String name) { marker.setTitle(name); } - public void updatePosition(Float latitude, Float longitude) { + public void updatePosition(Double latitude, Double longitude) { event.setLatitude(latitude); event.setLongitude(longitude); - marker.setPosition(new LatLng(latitude, longitude)); + if (latitude == null || longitude == null) { + marker.remove(); + } else { + marker.setPosition(new LatLng(latitude, longitude)); + } } public void replaceMarker(Marker marker) { diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/GoogleMapsFragment.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/GoogleMapsFragment.java index 058ecda..7c8c4db 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/GoogleMapsFragment.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/GoogleMapsFragment.java @@ -368,8 +368,8 @@ private static void updateWith(GMapEvent me, EventDTO update) { if (!update.getName().equals(me.getName())) { me.updateName(update.getName()); } - if (update.getLatitude() != me.getLatitude() - || update.getLongitude() != me.getLongitude()) { + if (!Objects.equals(update.getLatitude(), me.getLatitude()) + || !Objects.equals(update.getLongitude(), me.getLongitude())) { Log.d(TAG, "Location for event " + update.getName() + " " + update.getId() + " is changed. Moving the marker."); me.updatePosition(update.getLatitude(), update.getLongitude()); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java index 77c2a17..07a94d9 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java @@ -75,7 +75,9 @@ protected void onCreate(Bundle savedInstanceState) { logMethod(TAG, this); - validate(); + if (!validate()) { + return; + } ((App) getApplication()).getUserComponent().inject(this); @@ -88,22 +90,26 @@ protected void onCreate(Bundle savedInstanceState) { checkToken(this::onInit, this::finish, accountManager, this, tokenService); } - private void validate() { + private boolean validate() { Bundle extras = getIntent().getExtras(); if (extras == null) { Log.d(TAG, "Unable to create user activity without extras."); finish(); + return false; } userId = extras.getString(USER_ID_KEY); if (userId == null) { Log.d(TAG, "Unable to create user activity without 'user_id' provided."); finish(); + return false; } accountManager = AccountManager.get(this); if (userId.equals(AuthHelper.getUserUuid(accountManager))) { startActivity(new Intent(this, ProfileActivity.class)); finish(); + return false; } + return true; } private void onInit(String token) { diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/common/CommonHelper.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/common/CommonHelper.java index 7f03d1f..c3b629b 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/common/CommonHelper.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/common/CommonHelper.java @@ -66,6 +66,13 @@ public static Float getFloatOrNull(CharSequence input) { return Float.valueOf(input.toString()); } + public static Double getDoubleOrNull(CharSequence input) { + if (input == null || EMPTY_STR.contentEquals(input)) { + return null; + } + return Double.valueOf(input.toString()); + } + public static OffsetDateTime getOffsetDateTime(CharSequence input) { if (input == null || EMPTY_STR.contentEquals(input)) { return null; diff --git a/AndroidClient/src/main/res/values-en/strings.xml b/AndroidClient/src/main/res/values-en/strings.xml index 0ca3e27..e78aebb 100644 --- a/AndroidClient/src/main/res/values-en/strings.xml +++ b/AndroidClient/src/main/res/values-en/strings.xml @@ -205,6 +205,7 @@ Event photo Show on map Select position + Event location is not set yet. 360p diff --git a/AndroidClient/src/main/res/values-ru-rRU/strings.xml b/AndroidClient/src/main/res/values-ru-rRU/strings.xml index ce17217..cb5a7a6 100644 --- a/AndroidClient/src/main/res/values-ru-rRU/strings.xml +++ b/AndroidClient/src/main/res/values-ru-rRU/strings.xml @@ -203,6 +203,7 @@ Фото события Показать на карте Выбор местоположения + Местоположение события ещё не установлено. 360p diff --git a/AndroidClient/src/main/res/values/strings.xml b/AndroidClient/src/main/res/values/strings.xml index c951521..8d081b2 100644 --- a/AndroidClient/src/main/res/values/strings.xml +++ b/AndroidClient/src/main/res/values/strings.xml @@ -203,6 +203,7 @@ Event photo Show on map Select position + Event location is not set yet. 360p From 0af8efe4293c40a78bdcaa0f81b17f043c6f54d7 Mon Sep 17 00:00:00 2001 From: Georgy Lebedik Date: Wed, 25 Jun 2025 21:38:06 +0300 Subject: [PATCH 02/32] Inverting component dependencies. --- .../src/main/java/com/tom/meeter/App.java | 43 ++--------------- .../java/com/tom/meeter/AppComponent.java | 48 +++++++++---------- .../main/java/com/tom/meeter/AppModule.java | 18 +++---- .../{context/image => }/ImageModule.java | 3 +- .../{context/token => }/TokenModule.java | 2 +- .../meeter/{context/user => }/UserModule.java | 6 ++- .../meeter/context/auth/AuthComponent.java | 10 ++-- .../tom/meeter/context/auth/AuthModule.java | 4 +- .../auth/AuthScope.java} | 4 +- .../meeter/context/event/EventComponent.java | 15 ++---- .../meeter/context/image/ImageComponent.java | 27 ----------- .../image/activity/BaseUploadActivity.java | 2 +- .../tom/meeter/context/launcher/Launcher.java | 2 +- .../meeter/context/token/TokenComponent.java | 29 ----------- .../meeter/context/user/UserComponent.java | 20 ++------ 15 files changed, 63 insertions(+), 170 deletions(-) rename AndroidClient/src/main/java/com/tom/meeter/{context/image => }/ImageModule.java (92%) rename AndroidClient/src/main/java/com/tom/meeter/{context/token => }/TokenModule.java (96%) rename AndroidClient/src/main/java/com/tom/meeter/{context/user => }/UserModule.java (95%) rename AndroidClient/src/main/java/com/tom/meeter/{AppScope.java => context/auth/AuthScope.java} (70%) delete mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/image/ImageComponent.java delete mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/token/TokenComponent.java diff --git a/AndroidClient/src/main/java/com/tom/meeter/App.java b/AndroidClient/src/main/java/com/tom/meeter/App.java index 6356188..8fc5149 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/App.java +++ b/AndroidClient/src/main/java/com/tom/meeter/App.java @@ -9,10 +9,6 @@ import com.tom.meeter.context.auth.DaggerAuthComponent; import com.tom.meeter.context.event.DaggerEventComponent; import com.tom.meeter.context.event.EventComponent; -import com.tom.meeter.context.image.DaggerImageComponent; -import com.tom.meeter.context.image.ImageComponent; -import com.tom.meeter.context.token.DaggerTokenComponent; -import com.tom.meeter.context.token.TokenComponent; import com.tom.meeter.context.user.DaggerUserComponent; import com.tom.meeter.context.user.UserComponent; @@ -21,8 +17,6 @@ public class App extends Application { private static final String TAG = App.class.getCanonicalName(); private AppComponent component; private AuthComponent authComponent; - private TokenComponent tokenComponent; - private ImageComponent imageComponent; private EventComponent eventComponent; private UserComponent userComponent; @@ -31,16 +25,15 @@ public void onCreate() { super.onCreate(); logMethod(TAG, this); + component = buildComponent(); + /* Independent */ - tokenComponent = buildTokenComponent(); authComponent = buildAuthComponent(); - imageComponent = buildImageComponent(); /* Dependent */ eventComponent = buildEventComponent(); userComponent = buildUserComponent(); - component = buildComponent(); createNotificationChannel(this); } @@ -53,11 +46,6 @@ public void onTerminate() { protected AppComponent buildComponent() { return DaggerAppComponent.builder() - .tokenComponent(tokenComponent) - .imageComponent(imageComponent) - .authComponent(authComponent) - .eventComponent(eventComponent) - .userComponent(userComponent) .application(this) .build(); } @@ -65,34 +53,21 @@ protected AppComponent buildComponent() { protected AuthComponent buildAuthComponent() { return DaggerAuthComponent.builder() .application(this) - .build(); - } - - protected TokenComponent buildTokenComponent() { - return DaggerTokenComponent.builder() - .application(this) - .build(); - } - - protected ImageComponent buildImageComponent() { - return DaggerImageComponent.builder() - .application(this) + .appComponent(component) .build(); } protected EventComponent buildEventComponent() { return DaggerEventComponent.builder() .application(this) - .tokenComponent(tokenComponent) - .imageComponent(imageComponent) + .appComponent(component) .build(); } protected UserComponent buildUserComponent() { return DaggerUserComponent.builder() .application(this) - .tokenComponent(tokenComponent) - .imageComponent(imageComponent) + .appComponent(component) .build(); } @@ -104,18 +79,10 @@ public AuthComponent getAuthComponent() { return authComponent; } - public TokenComponent getTokenComponent() { - return tokenComponent; - } - public EventComponent getEventComponent() { return eventComponent; } - public ImageComponent getImageComponent() { - return imageComponent; - } - public UserComponent getUserComponent() { return userComponent; } diff --git a/AndroidClient/src/main/java/com/tom/meeter/AppComponent.java b/AndroidClient/src/main/java/com/tom/meeter/AppComponent.java index f665a4b..468cf12 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/AppComponent.java +++ b/AndroidClient/src/main/java/com/tom/meeter/AppComponent.java @@ -2,9 +2,9 @@ import android.app.Application; -import com.tom.meeter.context.auth.AuthComponent; -import com.tom.meeter.context.event.EventComponent; -import com.tom.meeter.context.image.ImageComponent; +import com.tom.meeter.context.image.ImageDownloader; +import com.tom.meeter.context.image.activity.BaseUploadActivity; +import com.tom.meeter.context.launcher.Launcher; import com.tom.meeter.context.profile.activity.ProfileActivity; import com.tom.meeter.context.profile.activity.SettingsActivity; import com.tom.meeter.context.profile.activity.SubscribersActivity; @@ -13,48 +13,44 @@ import com.tom.meeter.context.profile.fragment.GoogleMapsFragment; import com.tom.meeter.context.profile.fragment.ProfileEventsFragment; import com.tom.meeter.context.profile.fragment.ProfileFragment; -import com.tom.meeter.context.token.TokenComponent; -import com.tom.meeter.context.user.UserComponent; +import com.tom.meeter.context.token.service.TokenService; +import com.tom.meeter.context.user.service.UserService; import com.tom.meeter.infrastructure.injection.viewmodel.ViewModelModule; +import javax.inject.Singleton; + import dagger.BindsInstance; import dagger.Component; @Component( modules = { AppModule.class, - ViewModelModule.class - }, - dependencies = { - TokenComponent.class, - AuthComponent.class, - ImageComponent.class, - - EventComponent.class, - UserComponent.class + TokenModule.class, + ImageModule.class, + ViewModelModule.class, + UserModule.class }) -@AppScope +@Singleton public interface AppComponent { - @Component.Builder - interface Builder { - - @BindsInstance - Builder application(Application application); + TokenService provideTokenService(); - Builder authComponent(AuthComponent authComponent); + ImageDownloader provideImageDownloader(); - Builder tokenComponent(TokenComponent tokenComponent); + UserService provideUserService(); - Builder eventComponent(EventComponent eventComponent); - Builder imageComponent(ImageComponent imageComponent); + @Component.Builder + interface Builder { - Builder userComponent(UserComponent userComponent); + @BindsInstance + Builder application(Application application); AppComponent build(); } + void inject(Launcher launcher); + void inject(ProfileActivity profileActivity); void inject(SettingsActivity settingsActivity); @@ -71,4 +67,6 @@ interface Builder { void inject(SubscriptionsActivity subscriptionsActivity); + void inject(BaseUploadActivity baseUploadActivity); + } diff --git a/AndroidClient/src/main/java/com/tom/meeter/AppModule.java b/AndroidClient/src/main/java/com/tom/meeter/AppModule.java index efc0c8c..9e1effd 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/AppModule.java +++ b/AndroidClient/src/main/java/com/tom/meeter/AppModule.java @@ -27,6 +27,8 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import javax.inject.Singleton; + import dagger.Module; import dagger.Provides; import retrofit2.Retrofit; @@ -41,7 +43,7 @@ public AppModule() { Log.d(TAG, "Configuring AppModule..."); } - @AppScope + @Singleton @NonNull @Provides public ProfileService provideProfileService(Application app) { @@ -59,7 +61,7 @@ public ProfileService provideProfileService(Application app) { .create(ProfileService.class); } - @AppScope + @Singleton @NonNull @Provides public UserDatabase provideUserDb(Application app) { @@ -68,14 +70,14 @@ public UserDatabase provideUserDb(Application app) { .build(); } - @AppScope + @Singleton @NonNull @Provides public UserDao provideUserDao(UserDatabase userDatabase) { return userDatabase.userDao(); } - @AppScope + @Singleton @NonNull @Provides public Executor provideExecutor() { @@ -83,7 +85,7 @@ public Executor provideExecutor() { new ArrayBlockingQueue<>(15, false)); } - @AppScope + @Singleton @NonNull @Provides public EventDatabase provideEventDb(Application app) { @@ -92,14 +94,14 @@ public EventDatabase provideEventDb(Application app) { .build(); } - @AppScope + @Singleton @NonNull @Provides public EventDao provideEventDao(EventDatabase eventDatabase) { return eventDatabase.eventDao(); } - @AppScope + @Singleton @NonNull @Provides public SettingsService provideSettingsService(Application app) { @@ -111,7 +113,7 @@ public SettingsService provideSettingsService(Application app) { .create(SettingsService.class); } - @AppScope + @Singleton @NonNull @Provides public HttpClient provideHttpClient(Application app) { diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/image/ImageModule.java b/AndroidClient/src/main/java/com/tom/meeter/ImageModule.java similarity index 92% rename from AndroidClient/src/main/java/com/tom/meeter/context/image/ImageModule.java rename to AndroidClient/src/main/java/com/tom/meeter/ImageModule.java index 54f7b68..3200a59 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/image/ImageModule.java +++ b/AndroidClient/src/main/java/com/tom/meeter/ImageModule.java @@ -1,4 +1,4 @@ -package com.tom.meeter.context.image; +package com.tom.meeter; import static com.tom.meeter.infrastructure.common.Globals.getServerPath; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; @@ -7,6 +7,7 @@ import androidx.annotation.NonNull; +import com.tom.meeter.context.image.ImageDownloader; import com.tom.meeter.context.image.service.ImageService; import javax.inject.Singleton; diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/token/TokenModule.java b/AndroidClient/src/main/java/com/tom/meeter/TokenModule.java similarity index 96% rename from AndroidClient/src/main/java/com/tom/meeter/context/token/TokenModule.java rename to AndroidClient/src/main/java/com/tom/meeter/TokenModule.java index b76c7b4..0cc023f 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/token/TokenModule.java +++ b/AndroidClient/src/main/java/com/tom/meeter/TokenModule.java @@ -1,4 +1,4 @@ -package com.tom.meeter.context.token; +package com.tom.meeter; import static com.tom.meeter.infrastructure.common.Globals.getServerPath; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/UserModule.java b/AndroidClient/src/main/java/com/tom/meeter/UserModule.java similarity index 95% rename from AndroidClient/src/main/java/com/tom/meeter/context/user/UserModule.java rename to AndroidClient/src/main/java/com/tom/meeter/UserModule.java index ebfa342..544d78b 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/UserModule.java +++ b/AndroidClient/src/main/java/com/tom/meeter/UserModule.java @@ -1,4 +1,4 @@ -package com.tom.meeter.context.user; +package com.tom.meeter; import static com.tom.meeter.infrastructure.common.Globals.getServerPath; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; @@ -14,6 +14,8 @@ import java.util.TimeZone; +import javax.inject.Singleton; + import dagger.Module; import dagger.Provides; import retrofit2.Retrofit; @@ -28,7 +30,7 @@ public UserModule() { logMethod(TAG, this); } - @UserScope + @Singleton @NonNull @Provides public UserService provideUserService(Application app) { diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/auth/AuthComponent.java b/AndroidClient/src/main/java/com/tom/meeter/context/auth/AuthComponent.java index 4828d15..cde4543 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/auth/AuthComponent.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/auth/AuthComponent.java @@ -2,17 +2,17 @@ import android.app.Application; +import com.tom.meeter.AppComponent; import com.tom.meeter.context.auth.activity.LoginActivity; import com.tom.meeter.context.auth.activity.RegistrationActivity; import com.tom.meeter.context.auth.infrastructure.AccountAuthenticator; -import javax.inject.Singleton; - import dagger.BindsInstance; import dagger.Component; -@Singleton -@Component(modules = {AuthModule.class}) +@AuthScope +@Component(modules = {AuthModule.class}, + dependencies = {AppComponent.class}) public interface AuthComponent { @Component.Builder @@ -20,6 +20,8 @@ interface Builder { @BindsInstance Builder application(Application application); + Builder appComponent(AppComponent appComponent); + AuthComponent build(); } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/auth/AuthModule.java b/AndroidClient/src/main/java/com/tom/meeter/context/auth/AuthModule.java index 3ab22e7..9878e94 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/auth/AuthModule.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/auth/AuthModule.java @@ -10,8 +10,6 @@ import com.tom.meeter.AppModule; import com.tom.meeter.context.auth.service.AuthService; -import javax.inject.Singleton; - import dagger.Module; import dagger.Provides; import retrofit2.Retrofit; @@ -27,7 +25,7 @@ public AuthModule() { logMethod(TAG, this); } - @Singleton + @AuthScope @NonNull @Provides public AuthService provideAuthService(Application app) { diff --git a/AndroidClient/src/main/java/com/tom/meeter/AppScope.java b/AndroidClient/src/main/java/com/tom/meeter/context/auth/AuthScope.java similarity index 70% rename from AndroidClient/src/main/java/com/tom/meeter/AppScope.java rename to AndroidClient/src/main/java/com/tom/meeter/context/auth/AuthScope.java index 1a8e43c..6afa16d 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/AppScope.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/auth/AuthScope.java @@ -1,4 +1,4 @@ -package com.tom.meeter; +package com.tom.meeter.context.auth; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -7,5 +7,5 @@ @Scope @Retention(RetentionPolicy.RUNTIME) -public @interface AppScope { +public @interface AuthScope { } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/EventComponent.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/EventComponent.java index 74eda43..0c36e35 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/EventComponent.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/EventComponent.java @@ -2,15 +2,13 @@ import android.app.Application; +import com.tom.meeter.AppComponent; import com.tom.meeter.context.event.activity.EventDispatcherActivity; import com.tom.meeter.context.event.activity.EventLocationMapActivity; import com.tom.meeter.context.event.activity.EventOnMapActivity; import com.tom.meeter.context.event.activity.ProfileEventActivity; import com.tom.meeter.context.event.activity.UserEventActivity; -import com.tom.meeter.context.event.service.EventService; import com.tom.meeter.context.event.viewmodel.EventViewModelModule; -import com.tom.meeter.context.image.ImageComponent; -import com.tom.meeter.context.token.TokenComponent; import dagger.BindsInstance; import dagger.Component; @@ -21,22 +19,15 @@ EventModule.class, EventViewModelModule.class }, - dependencies = { - TokenComponent.class, - ImageComponent.class - }) + dependencies = {AppComponent.class}) public interface EventComponent { - EventService provideEventService(); - @Component.Builder interface Builder { @BindsInstance Builder application(Application application); - Builder tokenComponent(TokenComponent tokenComponent); - - Builder imageComponent(ImageComponent tokenComponent); + Builder appComponent(AppComponent appComponent); EventComponent build(); } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/image/ImageComponent.java b/AndroidClient/src/main/java/com/tom/meeter/context/image/ImageComponent.java deleted file mode 100644 index ac567e0..0000000 --- a/AndroidClient/src/main/java/com/tom/meeter/context/image/ImageComponent.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.tom.meeter.context.image; - -import android.app.Application; - -import com.tom.meeter.context.image.activity.BaseUploadActivity; - -import javax.inject.Singleton; - -import dagger.BindsInstance; -import dagger.Component; - -@Singleton -@Component(modules = {ImageModule.class}) -public interface ImageComponent { - - ImageDownloader provideImageDownloader(); - - @Component.Builder - interface Builder { - @BindsInstance - Builder application(Application application); - - ImageComponent build(); - } - - void inject(BaseUploadActivity baseUploadActivity); -} diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/image/activity/BaseUploadActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/image/activity/BaseUploadActivity.java index 41c245d..3c65dcd 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/image/activity/BaseUploadActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/image/activity/BaseUploadActivity.java @@ -58,7 +58,7 @@ protected void onCreate(Bundle savedInstanceState) { View view = binding.getRoot(); setContentView(view); - ((App) getApplication()).getImageComponent().inject(this); + ((App) getApplication()).getComponent().inject(this); accountManager = AccountManager.get(this); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/launcher/Launcher.java b/AndroidClient/src/main/java/com/tom/meeter/context/launcher/Launcher.java index b437678..5ecc578 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/launcher/Launcher.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/launcher/Launcher.java @@ -49,7 +49,7 @@ public class Launcher extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); logMethod(TAG, this); - ((App) getApplication()).getTokenComponent().inject(this); + ((App) getApplication()).getComponent().inject(this); accountManager = AccountManager.get(this); binding = LauncherBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/token/TokenComponent.java b/AndroidClient/src/main/java/com/tom/meeter/context/token/TokenComponent.java deleted file mode 100644 index 46f0161..0000000 --- a/AndroidClient/src/main/java/com/tom/meeter/context/token/TokenComponent.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.tom.meeter.context.token; - -import android.app.Application; - -import com.tom.meeter.context.launcher.Launcher; -import com.tom.meeter.context.token.service.TokenService; - -import javax.inject.Singleton; - -import dagger.BindsInstance; -import dagger.Component; - -@Singleton -@Component(modules = {TokenModule.class}) -public interface TokenComponent { - - TokenService providesTokenService(); - - @Component.Builder - interface Builder { - @BindsInstance - Builder application(Application application); - - TokenComponent build(); - } - - - void inject(Launcher launcher); -} \ No newline at end of file diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/UserComponent.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/UserComponent.java index 43dfa64..4a9f2aa 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/UserComponent.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/UserComponent.java @@ -2,12 +2,10 @@ import android.app.Application; -import com.tom.meeter.context.image.ImageComponent; -import com.tom.meeter.context.token.TokenComponent; +import com.tom.meeter.AppComponent; import com.tom.meeter.context.user.activity.UserActivity; import com.tom.meeter.context.user.activity.UserSubscribersActivity; import com.tom.meeter.context.user.activity.UserSubscriptionsActivity; -import com.tom.meeter.context.user.service.UserService; import com.tom.meeter.context.user.viewmodel.UserViewModelModule; import dagger.BindsInstance; @@ -15,26 +13,16 @@ @UserScope @Component( - modules = { - UserModule.class, - UserViewModelModule.class - }, - dependencies = { - TokenComponent.class, - ImageComponent.class - }) + modules = {UserViewModelModule.class}, + dependencies = {AppComponent.class}) public interface UserComponent { - UserService provideUserService(); - @Component.Builder interface Builder { @BindsInstance Builder application(Application application); - Builder tokenComponent(TokenComponent tokenComponent); - - Builder imageComponent(ImageComponent tokenComponent); + Builder appComponent(AppComponent appComponent); UserComponent build(); } From 5b7f8edad5cd2dcdeded3d583036808ebae89c8b Mon Sep 17 00:00:00 2001 From: Georgy Lebedik Date: Thu, 26 Jun 2025 00:24:06 +0300 Subject: [PATCH 03/32] Extract singletons factories. --- .../java/com/tom/meeter/AppComponent.java | 9 +++- .../{context/event => }/EventModule.java | 6 ++- .../meeter/context/event/EventComponent.java | 5 +- .../event/factory/EventViewModelFactory.java | 47 +++++++++++++++++++ .../profile/fragment/ProfileFragment.java | 4 +- .../context/user/activity/UserActivity.java | 24 +++++++++- .../activity/UserSubscribersActivity.java | 4 +- .../activity/UserSubscriptionsActivity.java | 4 +- .../user/factory/UserViewModelFactory.java | 47 +++++++++++++++++++ .../injection/viewmodel/ViewModelFactory.java | 7 ++- 10 files changed, 141 insertions(+), 16 deletions(-) rename AndroidClient/src/main/java/com/tom/meeter/{context/event => }/EventModule.java (96%) create mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/event/factory/EventViewModelFactory.java create mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserViewModelFactory.java diff --git a/AndroidClient/src/main/java/com/tom/meeter/AppComponent.java b/AndroidClient/src/main/java/com/tom/meeter/AppComponent.java index 468cf12..62fecc6 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/AppComponent.java +++ b/AndroidClient/src/main/java/com/tom/meeter/AppComponent.java @@ -2,6 +2,7 @@ import android.app.Application; +import com.tom.meeter.context.event.service.EventService; import com.tom.meeter.context.image.ImageDownloader; import com.tom.meeter.context.image.activity.BaseUploadActivity; import com.tom.meeter.context.launcher.Launcher; @@ -15,6 +16,7 @@ import com.tom.meeter.context.profile.fragment.ProfileFragment; import com.tom.meeter.context.token.service.TokenService; import com.tom.meeter.context.user.service.UserService; +import com.tom.meeter.infrastructure.injection.viewmodel.ViewModelFactory; import com.tom.meeter.infrastructure.injection.viewmodel.ViewModelModule; import javax.inject.Singleton; @@ -28,7 +30,8 @@ TokenModule.class, ImageModule.class, ViewModelModule.class, - UserModule.class + UserModule.class, + EventModule.class }) @Singleton public interface AppComponent { @@ -39,6 +42,10 @@ public interface AppComponent { UserService provideUserService(); + EventService provideEventService(); + + ViewModelFactory viewModelFactory(); + @Component.Builder interface Builder { diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/EventModule.java b/AndroidClient/src/main/java/com/tom/meeter/EventModule.java similarity index 96% rename from AndroidClient/src/main/java/com/tom/meeter/context/event/EventModule.java rename to AndroidClient/src/main/java/com/tom/meeter/EventModule.java index 5bb0b9c..2708b1f 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/EventModule.java +++ b/AndroidClient/src/main/java/com/tom/meeter/EventModule.java @@ -1,4 +1,4 @@ -package com.tom.meeter.context.event; +package com.tom.meeter; import static com.tom.meeter.infrastructure.common.Globals.getServerPath; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; @@ -16,6 +16,8 @@ import java.util.TimeZone; +import javax.inject.Singleton; + import dagger.Module; import dagger.Provides; import retrofit2.Retrofit; @@ -30,7 +32,7 @@ public EventModule() { logMethod(TAG, this); } - @EventScope + @Singleton @NonNull @Provides public EventService provideEventService(Application app) { diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/EventComponent.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/EventComponent.java index 0c36e35..df01fb2 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/EventComponent.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/EventComponent.java @@ -15,10 +15,7 @@ @EventScope @Component( - modules = { - EventModule.class, - EventViewModelModule.class - }, + modules = {EventViewModelModule.class}, dependencies = {AppComponent.class}) public interface EventComponent { diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/factory/EventViewModelFactory.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/factory/EventViewModelFactory.java new file mode 100644 index 0000000..be55824 --- /dev/null +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/factory/EventViewModelFactory.java @@ -0,0 +1,47 @@ +package com.tom.meeter.context.event.factory; + +import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; + +import android.util.Log; + +import androidx.lifecycle.ViewModel; +import androidx.lifecycle.ViewModelProvider; + +import com.tom.meeter.context.event.EventScope; +import com.tom.meeter.context.user.viewmodel.UserViewModelModule; + +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Provider; + +@EventScope +public class EventViewModelFactory implements ViewModelProvider.Factory { + + private static final String TAG = EventViewModelFactory.class.getCanonicalName(); + private final Map, Provider> viewModels; + + @Inject + public EventViewModelFactory(Map, Provider> viewModels) { + logMethod(TAG, this); + this.viewModels = viewModels; + } + + @Override + public T create(Class modelClass) { + Log.d(TAG, "EventViewModelFactory creates " + modelClass); + + Provider viewModelProvider = viewModels.get(modelClass); + + if (viewModelProvider == null) { + throw new IllegalArgumentException("ViewModel class " + modelClass + + " not found. Check " + UserViewModelModule.class.getCanonicalName() + + " file to be properly aligned."); + } + Log.d(TAG, "Before viewModelProvider.get() " + modelClass); + T t = (T) viewModelProvider.get(); + Log.d(TAG, "After viewModelProvider.get()" + modelClass); + + return t; + } +} diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileFragment.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileFragment.java index bfa502b..d15e021 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileFragment.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileFragment.java @@ -27,7 +27,7 @@ import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.lifecycle.LifecycleOwner; -import androidx.lifecycle.ViewModelProviders; +import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.GridLayoutManager; import com.tom.meeter.App; @@ -124,7 +124,7 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat super.onViewCreated(view, savedInstanceState); logMethod(TAG, this); - profileViewModel = ViewModelProviders.of(this, viewModelFactory) + profileViewModel = new ViewModelProvider(this, viewModelFactory) .get(ProfileViewModel.class); String authHeader = getAuthHeader(accountManager); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java index 07a94d9..aa1c269 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java @@ -33,13 +33,13 @@ import com.tom.meeter.context.token.service.TokenService; import com.tom.meeter.context.user.service.UserService; import com.tom.meeter.context.user.viewmodel.UserViewModel; +import com.tom.meeter.context.user.factory.UserViewModelFactory; import com.tom.meeter.databinding.ActivityUserBinding; import com.tom.meeter.infrastructure.common.Globals; import com.tom.meeter.infrastructure.components.adapter.EventsCardAdapter; import com.tom.meeter.infrastructure.components.binder.PhotoDownloaderEventBinder; import com.tom.meeter.infrastructure.http.HttpCodes; import com.tom.meeter.infrastructure.http.HttpErrorLogger; -import com.tom.meeter.infrastructure.injection.viewmodel.ViewModelFactory; import java.time.LocalDate; @@ -58,7 +58,7 @@ public class UserActivity extends AppCompatActivity { @Inject UserService userService; @Inject - ViewModelFactory viewModelFactory; + UserViewModelFactory viewModelFactory; @Inject ImageDownloader imgDownloader; @@ -202,6 +202,26 @@ public View onCreateView( return super.onCreateView(parent, name, ctx, attrs); } + @Override + protected void onDestroy() { + logMethod(TAG, this); + super.onDestroy(); + } + + @Override + protected void onStop() { + logMethod(TAG, this); + super.onStop(); + } + + @Override + protected void onPause() { + logMethod(TAG, this); + super.onPause(); + } + + + public static void dispatchToUserActivity(Context ctx, String userId) { ctx.startActivity(createUserActivityIntent(ctx, userId)); } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscribersActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscribersActivity.java index 38b1881..980da37 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscribersActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscribersActivity.java @@ -24,9 +24,9 @@ import com.tom.meeter.context.token.service.TokenService; import com.tom.meeter.context.user.adapter.UsersAdapter; import com.tom.meeter.context.user.viewmodel.UserSubscribersViewModel; +import com.tom.meeter.context.user.factory.UserViewModelFactory; import com.tom.meeter.databinding.ActivityProfileSubscribersBinding; import com.tom.meeter.infrastructure.components.binder.PhotoDownloaderWithCacheUserBinder; -import com.tom.meeter.infrastructure.injection.viewmodel.ViewModelFactory; import javax.inject.Inject; @@ -37,7 +37,7 @@ public class UserSubscribersActivity extends AppCompatActivity { @Inject TokenService tokenService; @Inject - ViewModelFactory viewModelFactory; + UserViewModelFactory viewModelFactory; @Inject ImageDownloader imgDownloader; diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscriptionsActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscriptionsActivity.java index 754d1e3..6bd1ee2 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscriptionsActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscriptionsActivity.java @@ -24,9 +24,9 @@ import com.tom.meeter.context.token.service.TokenService; import com.tom.meeter.context.user.adapter.UsersAdapter; import com.tom.meeter.context.user.viewmodel.UserSubscriptionsViewModel; +import com.tom.meeter.context.user.factory.UserViewModelFactory; import com.tom.meeter.databinding.ActivityProfileSubscriptionsBinding; import com.tom.meeter.infrastructure.components.binder.PhotoDownloaderWithCacheUserBinder; -import com.tom.meeter.infrastructure.injection.viewmodel.ViewModelFactory; import javax.inject.Inject; @@ -37,7 +37,7 @@ public class UserSubscriptionsActivity extends AppCompatActivity { @Inject TokenService tokenService; @Inject - ViewModelFactory viewModelFactory; + UserViewModelFactory viewModelFactory; @Inject ImageDownloader imgDownloader; diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserViewModelFactory.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserViewModelFactory.java new file mode 100644 index 0000000..54f47d7 --- /dev/null +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserViewModelFactory.java @@ -0,0 +1,47 @@ +package com.tom.meeter.context.user.factory; + +import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; + +import android.util.Log; + +import androidx.lifecycle.ViewModel; +import androidx.lifecycle.ViewModelProvider; + +import com.tom.meeter.context.user.UserScope; +import com.tom.meeter.context.user.viewmodel.UserViewModelModule; + +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Provider; + +@UserScope +public class UserViewModelFactory implements ViewModelProvider.Factory { + + private static final String TAG = UserViewModelFactory.class.getCanonicalName(); + private final Map, Provider> viewModels; + + @Inject + public UserViewModelFactory(Map, Provider> viewModels) { + logMethod(TAG, this); + this.viewModels = viewModels; + } + + @Override + public T create(Class modelClass) { + Log.d(TAG, "UserViewModelFactory creates " + modelClass); + + Provider viewModelProvider = viewModels.get(modelClass); + + if (viewModelProvider == null) { + throw new IllegalArgumentException("ViewModel class " + modelClass + + " not found. Check " + UserViewModelModule.class.getCanonicalName() + + " file to be properly aligned."); + } + Log.d(TAG, "Before viewModelProvider.get() " + modelClass); + T t = (T) viewModelProvider.get(); + Log.d(TAG, "After viewModelProvider.get()" + modelClass); + + return t; + } +} diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/injection/viewmodel/ViewModelFactory.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/injection/viewmodel/ViewModelFactory.java index 690b835..d884280 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/injection/viewmodel/ViewModelFactory.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/injection/viewmodel/ViewModelFactory.java @@ -11,7 +11,9 @@ import javax.inject.Inject; import javax.inject.Provider; +import javax.inject.Singleton; +@Singleton public class ViewModelFactory implements ViewModelProvider.Factory { private static final String TAG = ViewModelFactory.class.getCanonicalName(); @@ -34,7 +36,10 @@ public T create(Class modelClass) { + " not found. Check " + ViewModelModule.class.getCanonicalName() + " file to be properly aligned."); } + Log.d(TAG, "Before viewModelProvider.get() " + modelClass); + T t = (T) viewModelProvider.get(); + Log.d(TAG, "After viewModelProvider.get()" + modelClass); - return (T) viewModelProvider.get(); + return t; } } From e3c357cd24bf1634c890461e836f843e1b3e5b3b Mon Sep 17 00:00:00 2001 From: Georgy Lebedik Date: Thu, 26 Jun 2025 04:24:26 +0300 Subject: [PATCH 04/32] Raw approach for viewModel factories. --- .../activity/EventLocationMapActivity.java | 5 +- .../event/activity/EventOnMapActivity.java | 5 +- .../event/activity/ProfileEventActivity.java | 52 +++++++---- .../event/activity/UserEventActivity.java | 41 +++++--- .../event/factory/EventViewModelFactory.java | 1 + .../event/viewmodel/EventViewModel.java | 93 ++++++++++++++----- .../event/viewmodel/EventViewModelModule.java | 17 ++-- .../meeter/context/image/ImageDownloader.java | 27 ++++++ .../context/user/activity/UserActivity.java | 11 +-- .../infrastructure/common/ImagesHelper.java | 4 + 10 files changed, 185 insertions(+), 71 deletions(-) diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventLocationMapActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventLocationMapActivity.java index 693dc12..4f8fad3 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventLocationMapActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventLocationMapActivity.java @@ -51,7 +51,6 @@ public class EventLocationMapActivity extends AppCompatActivity implements OnMapReadyCallback { private static final String TAG = EventLocationMapActivity.class.getCanonicalName(); - private static final String EVENT_ID_KEY = "event_id"; private Marker eventMarker; private GoogleMap gmap; private ActivityEventPositionBinding binding; @@ -79,7 +78,7 @@ protected void onCreate(Bundle savedInstanceState) { showMessage(this, "Unable to show map without extras provided."); finish(); } - eventId = extras.getString(EVENT_ID_KEY); + eventId = extras.getString(EventDispatcherActivity.EVENT_ID_KEY); if (eventId == null) { showMessage(this, "Unable to show map without event_id provided."); finish(); @@ -229,7 +228,7 @@ public static void dispatchToEventLocationMapActivity( public static Intent createEventLocationMapActivityIntent(Context ctx, String eventId) { Intent result = new Intent(ctx, EventLocationMapActivity.class); - result.putExtra(EVENT_ID_KEY, eventId); + result.putExtra(EventDispatcherActivity.EVENT_ID_KEY, eventId); return result; } } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventOnMapActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventOnMapActivity.java index ca43d9c..a02ea0c 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventOnMapActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventOnMapActivity.java @@ -42,7 +42,6 @@ public class EventOnMapActivity extends AppCompatActivity implements OnMapReadyCallback { private static final String TAG = EventOnMapActivity.class.getCanonicalName(); - private static final String EVENT_ID_KEY = "event_id"; private GoogleMap gmap; private ActivityEventOnMapBinding binding; @@ -63,7 +62,7 @@ protected void onCreate(Bundle savedInstanceState) { showMessage(this, "Unable to show map without extras provided."); finish(); } - eventId = extras.getString(EVENT_ID_KEY); + eventId = extras.getString(EventDispatcherActivity.EVENT_ID_KEY); if (eventId == null) { showMessage(this, "Unable to show map without event_id provided."); finish(); @@ -151,7 +150,7 @@ public static void dispatchToEventOnMapActivity(Context ctx, String eventId) { public static Intent createEventOnMapActivityIntent( Context ctx, String eventId) { Intent result = new Intent(ctx, EventOnMapActivity.class); - result.putExtra(EVENT_ID_KEY, eventId); + result.putExtra(EventDispatcherActivity.EVENT_ID_KEY, eventId); return result; } } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/ProfileEventActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/ProfileEventActivity.java index 5cc2467..76a97a0 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/ProfileEventActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/ProfileEventActivity.java @@ -10,7 +10,6 @@ import static com.tom.meeter.infrastructure.common.CommonHelper.dateOrNull; import static com.tom.meeter.infrastructure.common.CommonHelper.textOrNull; import static com.tom.meeter.infrastructure.common.DateHelper.showDateTimePicker; -import static com.tom.meeter.infrastructure.common.ImagesHelper.circleImage; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.showMessage; @@ -18,6 +17,7 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; +import android.graphics.Bitmap; import android.os.Bundle; import android.util.AttributeSet; import android.util.Log; @@ -29,7 +29,7 @@ import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; -import androidx.lifecycle.ViewModelProviders; +import androidx.lifecycle.ViewModelProvider; import com.tom.meeter.App; import com.tom.meeter.R; @@ -44,16 +44,15 @@ import com.tom.meeter.context.token.service.TokenService; import com.tom.meeter.databinding.ActivityEventEditableBinding; import com.tom.meeter.infrastructure.common.Globals; +import com.tom.meeter.infrastructure.common.ImagesHelper; import com.tom.meeter.infrastructure.http.ActivityRecreatorOnAuthFailure; import com.tom.meeter.infrastructure.http.HttpCodes; import com.tom.meeter.infrastructure.http.HttpErrorLogger; -import com.tom.meeter.infrastructure.injection.viewmodel.ViewModelFactory; import java.util.Objects; import javax.inject.Inject; -import okhttp3.ResponseBody; import retrofit2.Call; import retrofit2.Response; @@ -69,17 +68,17 @@ public class ProfileEventActivity extends AppCompatActivity { @Inject EventService eventService; @Inject - ViewModelFactory viewModelFactory; + EventViewModel.EventViewModelAssistedFactory factory; @Inject ImageDownloader imgDownloader; private ActivityEventEditableBinding binding; private AccountManager accountManager; - private EventViewModel eventViewModel; + private EventViewModel viewModel; private ActivityResultLauncher mapResult; private EventDTO eventCache; - private ResponseBody photoCache; + private Bitmap photoCache; private boolean isEditableModeEnabled = false; private final ActivityResultLauncher imageUploadLauncher = @@ -96,13 +95,13 @@ public class ProfileEventActivity extends AppCompatActivity { void downloadAndUpdateLayoutPhoto(String photoPath) { imgDownloader.downloadEventImage(photoPath, this, - this::updateLayoutPhoto, - this::recreate); + this::updateLayoutPhoto, ImagesHelper::bigCircleImage, + this::recreate); } - private void updateLayoutPhoto(ResponseBody photo) { + private void updateLayoutPhoto(Bitmap photo) { photoCache = photo; - binding.photo.setImageBitmap(circleImage(photoCache, 600, 600)); + binding.photo.setImageBitmap(photoCache); } private void switchEditMode() { @@ -164,10 +163,14 @@ protected void onCreate(Bundle savedInstanceState) { } private void onInit(String token, String eventId) { - eventViewModel = ViewModelProviders.of(this, viewModelFactory) + ViewModelProvider.Factory factory = EventViewModel.providesFactory( + this.factory, eventId, token, this, + this::recreate, this::recreate); + viewModel = new ViewModelProvider(this, factory) .get(EventViewModel.class); - eventViewModel.fetchEventInformation(token, eventId, this); - eventViewModel.getEventLiveData() + initLayout(token); + + viewModel.getEvent() .observe(this, event -> { String userUuid = AuthHelper.getUserUuid(accountManager); String eventCreatorId = event.getCreatorId(); @@ -179,9 +182,8 @@ private void onInit(String token, String eventId) { eventCache = event; updateLayout(); }); - eventViewModel.getEventPhotoLiveData() + viewModel.getEventPhoto() .observe(this, this::updateLayoutPhoto); - initLayout(token); } private void initLayout(String token) { @@ -275,6 +277,24 @@ public View onCreateView( return super.onCreateView(parent, name, ctx, attrs); } + @Override + protected void onDestroy() { + logMethod(TAG, this); + super.onDestroy(); + } + + @Override + protected void onStop() { + logMethod(TAG, this); + super.onStop(); + } + + @Override + protected void onPause() { + logMethod(TAG, this); + super.onPause(); + } + public static void dispatchToProfileEventActivity(Context ctx, String eventId) { ctx.startActivity(createProfileEventActivityIntent(ctx, eventId)); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/UserEventActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/UserEventActivity.java index 634306c..22fd8d8 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/UserEventActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/UserEventActivity.java @@ -20,7 +20,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; -import androidx.lifecycle.ViewModelProviders; +import androidx.lifecycle.ViewModelProvider; import com.tom.meeter.App; import com.tom.meeter.context.auth.infrastructure.AuthHelper; @@ -29,7 +29,6 @@ import com.tom.meeter.context.network.dto.EventDTO; import com.tom.meeter.context.token.service.TokenService; import com.tom.meeter.databinding.ActivityEventReadableBinding; -import com.tom.meeter.infrastructure.injection.viewmodel.ViewModelFactory; import javax.inject.Inject; @@ -37,14 +36,15 @@ public class UserEventActivity extends AppCompatActivity { private static final String TAG = UserEventActivity.class.getCanonicalName(); - ActivityEventReadableBinding binding; @Inject TokenService tokenService; @Inject EventService eventService; @Inject - ViewModelFactory viewModelFactory; - private EventViewModel eventViewModel; + EventViewModel.EventViewModelAssistedFactory factory; + + ActivityEventReadableBinding binding; + private EventViewModel viewModel; private AccountManager accountManager; @Override @@ -75,10 +75,12 @@ protected void onCreate(Bundle savedInstanceState) { } private void onInit(String token, String eventId) { - eventViewModel = ViewModelProviders.of(this, viewModelFactory) + ViewModelProvider.Factory factory = EventViewModel.providesFactory( + this.factory, eventId, token, this, + this::recreate, this::recreate); + viewModel = new ViewModelProvider(this, factory) .get(EventViewModel.class); - eventViewModel.fetchEventInformation(token, eventId, this); - eventViewModel.getEventLiveData() + viewModel.getEvent() .observe(this, event -> { String userUuid = AuthHelper.getUserUuid(accountManager); String eventCreatorId = event.getCreatorId(); @@ -88,10 +90,10 @@ private void onInit(String token, String eventId) { finish(); } initLayout(event); - eventViewModel.getEventPhotoLiveData() + viewModel.getEventPhoto() .observe( - this, photo -> binding.eventPhoto.setImageBitmap( - circleImage(photo, 600, 600))); + this, + photo -> binding.eventPhoto.setImageBitmap(photo)); }); } @@ -124,6 +126,23 @@ public View onCreateView( return super.onCreateView(parent, name, ctx, attrs); } + @Override + protected void onDestroy() { + logMethod(TAG, this); + super.onDestroy(); + } + + @Override + protected void onStop() { + logMethod(TAG, this); + super.onStop(); + } + + @Override + protected void onPause() { + logMethod(TAG, this); + super.onPause(); + } public static void dispatchToUserEventActivity(Context ctx, String eventId) { ctx.startActivity(createUserEventActivityIntent(ctx, eventId)); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/factory/EventViewModelFactory.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/factory/EventViewModelFactory.java index be55824..0ce7434 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/factory/EventViewModelFactory.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/factory/EventViewModelFactory.java @@ -19,6 +19,7 @@ public class EventViewModelFactory implements ViewModelProvider.Factory { private static final String TAG = EventViewModelFactory.class.getCanonicalName(); + private final Map, Provider> viewModels; @Inject diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModel.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModel.java index ff37c3d..96592ea 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModel.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModel.java @@ -2,64 +2,112 @@ import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; -import android.app.Activity; +import android.content.Context; +import android.graphics.Bitmap; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.ViewModel; +import androidx.lifecycle.ViewModelProvider; import com.tom.meeter.context.event.service.EventService; import com.tom.meeter.context.image.ImageDownloader; import com.tom.meeter.context.network.dto.EventDTO; import com.tom.meeter.context.user.viewmodel.UserViewModel; import com.tom.meeter.infrastructure.common.Globals; +import com.tom.meeter.infrastructure.common.ImagesHelper; import com.tom.meeter.infrastructure.http.HttpCodes; import com.tom.meeter.infrastructure.http.HttpErrorLogger; -import javax.inject.Inject; - -import okhttp3.ResponseBody; +import dagger.assisted.Assisted; +import dagger.assisted.AssistedFactory; +import dagger.assisted.AssistedInject; import retrofit2.Call; import retrofit2.Response; public class EventViewModel extends ViewModel { private static final String TAG = UserViewModel.class.getCanonicalName(); - - private final MutableLiveData eventLiveData = new MutableLiveData<>(); - private final MutableLiveData eventPhotoLiveData = new MutableLiveData<>(); + private static final String ASSISTED_EVENT = "event_id"; + private static final String ASSISTED_TOKEN = "token"; + private static final String ASSISTED_ON_NOT_AUTHENTICATED = "on_not_authenticated"; + private static final String ASSISTED_ON_AUTH_FAIL = "on_auth_fail"; private final EventService eventService; private final ImageDownloader imageDownloader; - - @Inject - public EventViewModel(EventService eventService, ImageDownloader imageDownloader) { + private final String eventId; + private final String token; + private final Context ctx; + private final Runnable onNotAuthenticated; + private final Runnable onAuthFail; + + + private final MutableLiveData event = new MutableLiveData<>(); + private final MutableLiveData eventPhoto = new MutableLiveData<>(); + + @AssistedInject + public EventViewModel( + EventService eventService, ImageDownloader imageDownloader, + @Assisted(ASSISTED_EVENT) String eventId, + @Assisted(ASSISTED_TOKEN) String token, + @Assisted Context ctx, + @Assisted(ASSISTED_ON_NOT_AUTHENTICATED) Runnable onNotAuthenticated, + @Assisted(ASSISTED_ON_AUTH_FAIL) Runnable onAuthFail) { logMethod(TAG, this); this.eventService = eventService; this.imageDownloader = imageDownloader; + this.eventId = eventId; + this.token = token; + this.ctx = ctx.getApplicationContext(); + this.onNotAuthenticated = onNotAuthenticated; + this.onAuthFail = onAuthFail; + init(); + } + + @AssistedFactory + public interface EventViewModelAssistedFactory { + EventViewModel create( + @Assisted(ASSISTED_EVENT) String eventId, + @Assisted(ASSISTED_TOKEN) String token, + @Assisted Context ctx, + @Assisted(ASSISTED_ON_NOT_AUTHENTICATED) Runnable onNotAuthenticated, + @Assisted(ASSISTED_ON_AUTH_FAIL) Runnable onAuthFail); + } + + public static ViewModelProvider.Factory providesFactory( + EventViewModelAssistedFactory assistedFactory, + String eventId, String token, Context ctx, + Runnable onNotAuthenticated, Runnable onAuthFail) { + return new ViewModelProvider.Factory() { + @Override + @SuppressWarnings("unchecked") + public T create(Class modelClass) { + return (T) assistedFactory.create( + eventId, token, ctx, onNotAuthenticated, onAuthFail); + } + }; } - public void fetchEventInformation(String token, String eventId, Activity activity) { + public void init() { eventService.getEvent(Globals.getAuthHeader(token), eventId).enqueue( - new HttpErrorLogger<>(activity) { + //TODO check toast... + new HttpErrorLogger<>(ctx) { @Override public void onResponse(Call call, Response resp) { super.onResponse(call, resp); EventDTO body = resp.body(); if (resp.code() == HttpCodes.OK && body != null) { - eventLiveData.setValue(body); + event.setValue(body); String photoPath = body.getPhotoPath(); if (photoPath != null) { imageDownloader.downloadEventImage( - photoPath, - activity.getApplicationContext(), - eventPhotoLiveData::setValue, - activity::recreate); + photoPath, ctx, eventPhoto::setValue, + ImagesHelper::bigCircleImage, onAuthFail); } return; } if (resp.code() == HttpCodes.NOT_AUTHENTICATED) { - activity.recreate(); + onNotAuthenticated.run(); } } } @@ -72,12 +120,11 @@ protected void onCleared() { super.onCleared(); } - public LiveData getEventLiveData() { - return eventLiveData; + public LiveData getEvent() { + return event; } - public LiveData getEventPhotoLiveData() { - return eventPhotoLiveData; + public LiveData getEventPhoto() { + return eventPhoto; } } - diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModelModule.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModelModule.java index d79434b..94303ee 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModelModule.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModelModule.java @@ -1,17 +1,16 @@ package com.tom.meeter.context.event.viewmodel; -import androidx.lifecycle.ViewModel; - -import com.tom.meeter.infrastructure.injection.viewmodel.ViewModelKey; - -import dagger.Binds; import dagger.Module; -import dagger.multibindings.IntoMap; @Module -public abstract class EventViewModelModule { - @Binds +public interface EventViewModelModule { +/* @Binds @IntoMap @ViewModelKey(EventViewModel.class) - abstract ViewModel eventViewModel(EventViewModel eventViewModel); + ViewModel eventViewModel(EventViewModel eventViewModel);*/ + +/* @Binds + EventViewModel.EventViewModelAssistedFactory bindFactory( + EventViewModel.EventViewModelAssistedFactory impl + );*/ } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/image/ImageDownloader.java b/AndroidClient/src/main/java/com/tom/meeter/context/image/ImageDownloader.java index a0093cd..1dfd9a0 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/image/ImageDownloader.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/image/ImageDownloader.java @@ -5,12 +5,14 @@ import android.accounts.AccountManager; import android.content.Context; +import android.graphics.Bitmap; import com.tom.meeter.context.image.service.ImageService; import com.tom.meeter.infrastructure.http.HttpCodes; import com.tom.meeter.infrastructure.http.HttpErrorLogger; import java.util.function.Consumer; +import java.util.function.Function; import javax.inject.Inject; @@ -29,6 +31,30 @@ public ImageDownloader(ImageService imageService) { this.imageService = imageService; } + public void downloadEventImage( + String photoPath, Context ctx, + Consumer onDownloaded, Function bodyConverter, + Runnable onNotAuthenticated) { + imageService.downloadEventImage(getAuthHeader(AccountManager.get(ctx)), photoPath) + .enqueue(new HttpErrorLogger<>(ctx) { + @Override + public void onResponse(Call call, Response response) { + super.onResponse(call, response); + //Log.d(TAG, "/images/event" + photoPath + " downloaded..."); + if (response.code() == HttpCodes.OK) { + try (ResponseBody body = response.body()) { + onDownloaded.accept(bodyConverter.apply(body)); + return; + } + } + if (response.code() == HttpCodes.NOT_AUTHENTICATED) { + onNotAuthenticated.run(); + } + } + }); + } + + @Deprecated public void downloadEventImage( String photoPath, Context ctx, Consumer onDownloaded, Runnable onNotAuthenticated) { @@ -51,6 +77,7 @@ public void onResponse(Call call, Response response) }); } + @Deprecated public void downloadUserImage( String photoPath, Context ctx, Consumer onDownloaded, Runnable onNotAuthenticated) { diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java index aa1c269..2790483 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java @@ -7,7 +7,7 @@ import static com.tom.meeter.infrastructure.common.CommonHelper.EMPTY_STR; import static com.tom.meeter.infrastructure.common.CommonHelper.genderResolver; import static com.tom.meeter.infrastructure.common.DateHelper.getAgeFromDate; -import static com.tom.meeter.infrastructure.common.ImagesHelper.circleImage; +import static com.tom.meeter.infrastructure.common.ImagesHelper.bigCircleImage; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.showMessage; @@ -22,7 +22,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; -import androidx.lifecycle.ViewModelProviders; +import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.GridLayoutManager; import com.tom.meeter.App; @@ -31,9 +31,9 @@ import com.tom.meeter.context.image.ImageDownloader; import com.tom.meeter.context.profile.activity.ProfileActivity; import com.tom.meeter.context.token.service.TokenService; +import com.tom.meeter.context.user.factory.UserViewModelFactory; import com.tom.meeter.context.user.service.UserService; import com.tom.meeter.context.user.viewmodel.UserViewModel; -import com.tom.meeter.context.user.factory.UserViewModelFactory; import com.tom.meeter.databinding.ActivityUserBinding; import com.tom.meeter.infrastructure.common.Globals; import com.tom.meeter.infrastructure.components.adapter.EventsCardAdapter; @@ -157,7 +157,7 @@ public void onResponse(Call call, Response resp) { } }); - userViewModel = ViewModelProviders.of(this, viewModelFactory) + userViewModel = new ViewModelProvider(this, viewModelFactory) .get(UserViewModel.class); userViewModel.fetchUserInformation(token, userId, this); userViewModel.getUserLiveData() @@ -178,7 +178,7 @@ public void onResponse(Call call, Response resp) { userViewModel.getUserPhotoLiveData() .observe( this, - photo -> binding.photo.setImageBitmap(circleImage(photo, 600, 600))); + photo -> binding.photo.setImageBitmap(bigCircleImage(photo))); binding.events.setLayoutManager(new GridLayoutManager(this, 2)); binding.events.setAdapter(adapter); @@ -221,7 +221,6 @@ protected void onPause() { } - public static void dispatchToUserActivity(Context ctx, String userId) { ctx.startActivity(createUserActivityIntent(ctx, userId)); } diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/common/ImagesHelper.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/common/ImagesHelper.java index 222dab4..488b76a 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/common/ImagesHelper.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/common/ImagesHelper.java @@ -43,6 +43,10 @@ public static Bitmap circleImage(ResponseBody body, int scaleWidth, int scaleHei return getCircleBitmap(Bitmap.createScaledBitmap(from, scaleWidth, scaleHeight, true)); } + public static Bitmap bigCircleImage(ResponseBody body) { + return circleImage(body, 600, 600); + } + public static Bitmap circleImage(Bitmap src) { return getCircleBitmap(Bitmap.createScaledBitmap(src, 150, 150, true)); } From c237f65000d00ca5ea84c4734cdfa00da4e069ef Mon Sep 17 00:00:00 2001 From: Georgy Lebedik Date: Thu, 26 Jun 2025 14:50:56 +0300 Subject: [PATCH 05/32] Small refactoring. --- .../meeter/context/event/EventComponent.java | 3 +- .../activity/EventDispatcherActivity.java | 4 +- .../event/activity/ProfileEventActivity.java | 7 ++-- .../event/activity/UserEventActivity.java | 3 +- .../event/viewmodel/EventViewModel.java | 40 +++++++------------ .../meeter/context/image/ImageDownloader.java | 17 ++------ .../profile/activity/SubscribersActivity.java | 6 +-- .../activity/SubscriptionsActivity.java | 6 +-- .../ProfileSubscribersViewModel.java | 6 +-- .../ProfileSubscriptionsViewModel.java | 4 +- .../context/user/activity/UserActivity.java | 12 ++---- .../viewmodel/UserSubscribersViewModel.java | 4 +- .../viewmodel/UserSubscriptionsViewModel.java | 4 +- .../context/user/viewmodel/UserViewModel.java | 8 ++-- .../http/ActivityRecreatorOnAuthFailure.java | 27 ------------- .../http/BaseOnNotAuthenticatedCallback.java | 28 +++++++++++++ .../infrastructure/http/DisconnectLogger.java | 2 +- .../infrastructure/http/ErrorLogger.java | 3 -- .../infrastructure/http/HttpErrorLogger.java | 3 -- 19 files changed, 77 insertions(+), 110 deletions(-) delete mode 100644 AndroidClient/src/main/java/com/tom/meeter/infrastructure/http/ActivityRecreatorOnAuthFailure.java create mode 100644 AndroidClient/src/main/java/com/tom/meeter/infrastructure/http/BaseOnNotAuthenticatedCallback.java diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/EventComponent.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/EventComponent.java index df01fb2..8933210 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/EventComponent.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/EventComponent.java @@ -8,14 +8,13 @@ import com.tom.meeter.context.event.activity.EventOnMapActivity; import com.tom.meeter.context.event.activity.ProfileEventActivity; import com.tom.meeter.context.event.activity.UserEventActivity; -import com.tom.meeter.context.event.viewmodel.EventViewModelModule; import dagger.BindsInstance; import dagger.Component; @EventScope @Component( - modules = {EventViewModelModule.class}, +/* modules = {EventViewModelModule.class},*/ dependencies = {AppComponent.class}) public interface EventComponent { diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventDispatcherActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventDispatcherActivity.java index 129aa42..2aea752 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventDispatcherActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventDispatcherActivity.java @@ -17,7 +17,7 @@ import com.tom.meeter.context.event.service.EventService; import com.tom.meeter.context.token.service.TokenService; import com.tom.meeter.infrastructure.common.Globals; -import com.tom.meeter.infrastructure.http.ActivityRecreatorOnAuthFailure; +import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; import com.tom.meeter.infrastructure.http.HttpCodes; import javax.inject.Inject; @@ -66,7 +66,7 @@ protected void onCreate(Bundle savedInstanceState) { private void onInit(String token, String eventId) { eventService.amICreator(Globals.getAuthHeader(token), eventId) - .enqueue(new ActivityRecreatorOnAuthFailure<>(this) { + .enqueue(new BaseOnNotAuthenticatedCallback<>(this, this::recreate) { @Override public void onResponse(Call call, Response resp) { super.onResponse(call, resp); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/ProfileEventActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/ProfileEventActivity.java index 76a97a0..09d03a2 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/ProfileEventActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/ProfileEventActivity.java @@ -45,7 +45,7 @@ import com.tom.meeter.databinding.ActivityEventEditableBinding; import com.tom.meeter.infrastructure.common.Globals; import com.tom.meeter.infrastructure.common.ImagesHelper; -import com.tom.meeter.infrastructure.http.ActivityRecreatorOnAuthFailure; +import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; import com.tom.meeter.infrastructure.http.HttpCodes; import com.tom.meeter.infrastructure.http.HttpErrorLogger; @@ -164,8 +164,7 @@ protected void onCreate(Bundle savedInstanceState) { private void onInit(String token, String eventId) { ViewModelProvider.Factory factory = EventViewModel.providesFactory( - this.factory, eventId, token, this, - this::recreate, this::recreate); + this.factory, eventId, token, this, this::recreate); viewModel = new ViewModelProvider(this, factory) .get(EventViewModel.class); initLayout(token); @@ -209,7 +208,7 @@ private void initLayout(String token) { return; } eventService.updateEvent(Globals.getAuthHeader(token), eventCache.getId(), req) - .enqueue(new ActivityRecreatorOnAuthFailure<>(this) { + .enqueue(new BaseOnNotAuthenticatedCallback<>(this, this::recreate) { @Override public void onResponse(Call call, Response resp) { super.onResponse(call, resp); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/UserEventActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/UserEventActivity.java index 22fd8d8..6d2a897 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/UserEventActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/UserEventActivity.java @@ -76,8 +76,7 @@ protected void onCreate(Bundle savedInstanceState) { private void onInit(String token, String eventId) { ViewModelProvider.Factory factory = EventViewModel.providesFactory( - this.factory, eventId, token, this, - this::recreate, this::recreate); + this.factory, eventId, token, this, this::recreate); viewModel = new ViewModelProvider(this, factory) .get(EventViewModel.class); viewModel.getEvent() diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModel.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModel.java index 96592ea..f6948da 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModel.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModel.java @@ -16,8 +16,8 @@ import com.tom.meeter.context.user.viewmodel.UserViewModel; import com.tom.meeter.infrastructure.common.Globals; import com.tom.meeter.infrastructure.common.ImagesHelper; +import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; import com.tom.meeter.infrastructure.http.HttpCodes; -import com.tom.meeter.infrastructure.http.HttpErrorLogger; import dagger.assisted.Assisted; import dagger.assisted.AssistedFactory; @@ -30,8 +30,6 @@ public class EventViewModel extends ViewModel { private static final String TAG = UserViewModel.class.getCanonicalName(); private static final String ASSISTED_EVENT = "event_id"; private static final String ASSISTED_TOKEN = "token"; - private static final String ASSISTED_ON_NOT_AUTHENTICATED = "on_not_authenticated"; - private static final String ASSISTED_ON_AUTH_FAIL = "on_auth_fail"; private final EventService eventService; private final ImageDownloader imageDownloader; @@ -39,8 +37,6 @@ public class EventViewModel extends ViewModel { private final String token; private final Context ctx; private final Runnable onNotAuthenticated; - private final Runnable onAuthFail; - private final MutableLiveData event = new MutableLiveData<>(); private final MutableLiveData eventPhoto = new MutableLiveData<>(); @@ -51,8 +47,7 @@ public EventViewModel( @Assisted(ASSISTED_EVENT) String eventId, @Assisted(ASSISTED_TOKEN) String token, @Assisted Context ctx, - @Assisted(ASSISTED_ON_NOT_AUTHENTICATED) Runnable onNotAuthenticated, - @Assisted(ASSISTED_ON_AUTH_FAIL) Runnable onAuthFail) { + @Assisted Runnable onNotAuthenticated) { logMethod(TAG, this); this.eventService = eventService; this.imageDownloader = imageDownloader; @@ -60,7 +55,6 @@ public EventViewModel( this.token = token; this.ctx = ctx.getApplicationContext(); this.onNotAuthenticated = onNotAuthenticated; - this.onAuthFail = onAuthFail; init(); } @@ -70,20 +64,18 @@ EventViewModel create( @Assisted(ASSISTED_EVENT) String eventId, @Assisted(ASSISTED_TOKEN) String token, @Assisted Context ctx, - @Assisted(ASSISTED_ON_NOT_AUTHENTICATED) Runnable onNotAuthenticated, - @Assisted(ASSISTED_ON_AUTH_FAIL) Runnable onAuthFail); + @Assisted Runnable onNotAuthenticated); } public static ViewModelProvider.Factory providesFactory( EventViewModelAssistedFactory assistedFactory, String eventId, String token, Context ctx, - Runnable onNotAuthenticated, Runnable onAuthFail) { + Runnable onNotAuthenticated) { return new ViewModelProvider.Factory() { @Override @SuppressWarnings("unchecked") public T create(Class modelClass) { - return (T) assistedFactory.create( - eventId, token, ctx, onNotAuthenticated, onAuthFail); + return (T) assistedFactory.create(eventId, token, ctx, onNotAuthenticated); } }; } @@ -91,24 +83,22 @@ public T create(Class modelClass) { public void init() { eventService.getEvent(Globals.getAuthHeader(token), eventId).enqueue( //TODO check toast... - new HttpErrorLogger<>(ctx) { + new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { @Override public void onResponse(Call call, Response resp) { super.onResponse(call, resp); - EventDTO body = resp.body(); - if (resp.code() == HttpCodes.OK && body != null) { - event.setValue(body); - String photoPath = body.getPhotoPath(); - if (photoPath != null) { - imageDownloader.downloadEventImage( - photoPath, ctx, eventPhoto::setValue, - ImagesHelper::bigCircleImage, onAuthFail); - } + EventDTO eventResp = resp.body(); + if (resp.code() != HttpCodes.OK || eventResp == null) { return; } - if (resp.code() == HttpCodes.NOT_AUTHENTICATED) { - onNotAuthenticated.run(); + event.setValue(eventResp); + String photoPath = eventResp.getPhotoPath(); + if (photoPath == null) { + return; } + imageDownloader.downloadEventImage( + photoPath, ctx, eventPhoto::setValue, + ImagesHelper::bigCircleImage, onNotAuthenticated); } } ); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/image/ImageDownloader.java b/AndroidClient/src/main/java/com/tom/meeter/context/image/ImageDownloader.java index 1dfd9a0..1dd3875 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/image/ImageDownloader.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/image/ImageDownloader.java @@ -8,8 +8,8 @@ import android.graphics.Bitmap; import com.tom.meeter.context.image.service.ImageService; +import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; import com.tom.meeter.infrastructure.http.HttpCodes; -import com.tom.meeter.infrastructure.http.HttpErrorLogger; import java.util.function.Consumer; import java.util.function.Function; @@ -36,7 +36,7 @@ public void downloadEventImage( Consumer onDownloaded, Function bodyConverter, Runnable onNotAuthenticated) { imageService.downloadEventImage(getAuthHeader(AccountManager.get(ctx)), photoPath) - .enqueue(new HttpErrorLogger<>(ctx) { + .enqueue(new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { @Override public void onResponse(Call call, Response response) { super.onResponse(call, response); @@ -47,9 +47,6 @@ public void onResponse(Call call, Response response) return; } } - if (response.code() == HttpCodes.NOT_AUTHENTICATED) { - onNotAuthenticated.run(); - } } }); } @@ -59,7 +56,7 @@ public void downloadEventImage( String photoPath, Context ctx, Consumer onDownloaded, Runnable onNotAuthenticated) { imageService.downloadEventImage(getAuthHeader(AccountManager.get(ctx)), photoPath) - .enqueue(new HttpErrorLogger<>(ctx) { + .enqueue(new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { @Override public void onResponse(Call call, Response response) { super.onResponse(call, response); @@ -70,9 +67,6 @@ public void onResponse(Call call, Response response) return; } } - if (response.code() == HttpCodes.NOT_AUTHENTICATED) { - onNotAuthenticated.run(); - } } }); } @@ -82,7 +76,7 @@ public void downloadUserImage( String photoPath, Context ctx, Consumer onDownloaded, Runnable onNotAuthenticated) { imageService.downloadUserImage(getAuthHeader(AccountManager.get(ctx)), photoPath) - .enqueue(new HttpErrorLogger<>(ctx) { + .enqueue(new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { @Override public void onResponse(Call call, Response response) { super.onResponse(call, response); @@ -92,9 +86,6 @@ public void onResponse(Call call, Response response) return; } } - if (response.code() == HttpCodes.NOT_AUTHENTICATED) { - onNotAuthenticated.run(); - } } }); } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscribersActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscribersActivity.java index 69d4949..b5759fc 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscribersActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscribersActivity.java @@ -24,7 +24,7 @@ import com.tom.meeter.context.user.service.UserService; import com.tom.meeter.databinding.ActivityProfileSubscribersBinding; import com.tom.meeter.infrastructure.components.binder.PhotoDownloaderWithCacheSubscriberBinder; -import com.tom.meeter.infrastructure.http.ActivityRecreatorOnAuthFailure; +import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; import com.tom.meeter.infrastructure.http.HttpCodes; import com.tom.meeter.infrastructure.injection.viewmodel.ViewModelFactory; @@ -99,7 +99,7 @@ private void onInit(String token) { private void onSubUnsubClick(Subscriber sub, int position) { if (sub.isAmISubscribedTo()) { userService.unsubscribe(AuthHelper.getAuthHeader(accountManager), sub.getUser().getId()) - .enqueue(new ActivityRecreatorOnAuthFailure<>(this) { + .enqueue(new BaseOnNotAuthenticatedCallback<>(this, this::recreate) { @Override public void onResponse(Call call, Response resp) { super.onResponse(call, resp); @@ -111,7 +111,7 @@ public void onResponse(Call call, Response resp) { }); } else { userService.subscribe(AuthHelper.getAuthHeader(accountManager), sub.getUser().getId()) - .enqueue(new ActivityRecreatorOnAuthFailure<>(this) { + .enqueue(new BaseOnNotAuthenticatedCallback<>(this, this::recreate) { @Override public void onResponse(Call call, Response resp) { super.onResponse(call, resp); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscriptionsActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscriptionsActivity.java index c11c7f9..e8e532f 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscriptionsActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscriptionsActivity.java @@ -23,7 +23,7 @@ import com.tom.meeter.context.user.service.UserService; import com.tom.meeter.databinding.ActivityProfileSubscriptionsBinding; import com.tom.meeter.infrastructure.components.binder.PhotoDownloaderWithCacheSubscriberBinder; -import com.tom.meeter.infrastructure.http.ActivityRecreatorOnAuthFailure; +import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; import com.tom.meeter.infrastructure.injection.viewmodel.ViewModelFactory; import javax.inject.Inject; @@ -94,7 +94,7 @@ private void onInit(String token) { private void onSubUnsubClick(Subscriber sub, int position) { if (sub.isAmISubscribedTo()) { userService.unsubscribe(AuthHelper.getAuthHeader(accountManager), sub.getUser().getId()) - .enqueue(new ActivityRecreatorOnAuthFailure<>(this) { + .enqueue(new BaseOnNotAuthenticatedCallback<>(this, this::recreate) { @Override public void onResponse(Call call, Response response) { super.onResponse(call, response); @@ -104,7 +104,7 @@ public void onResponse(Call call, Response response) { }); } else { userService.subscribe(AuthHelper.getAuthHeader(accountManager), sub.getUser().getId()) - .enqueue(new ActivityRecreatorOnAuthFailure<>(this) { + .enqueue(new BaseOnNotAuthenticatedCallback<>(this, this::recreate) { @Override public void onResponse(Call call, Response response) { super.onResponse(call, response); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileSubscribersViewModel.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileSubscribersViewModel.java index 4d8498a..66cf711 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileSubscribersViewModel.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileSubscribersViewModel.java @@ -11,7 +11,7 @@ import com.tom.meeter.context.network.dto.UserDTO; import com.tom.meeter.context.profile.service.ProfileService; import com.tom.meeter.context.profile.subscriber.Subscriber; -import com.tom.meeter.infrastructure.http.ActivityRecreatorOnAuthFailure; +import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; import com.tom.meeter.infrastructure.http.HttpCodes; import java.util.ArrayList; @@ -40,7 +40,7 @@ public ProfileSubscribersViewModel(ProfileService profileService) { public void fetchProfileSubscribers(String auth, Activity activity) { profileService.getMySubscriptions(auth).enqueue( - new ActivityRecreatorOnAuthFailure<>(activity) { + new BaseOnNotAuthenticatedCallback<>(activity, activity::recreate) { @Override public void onResponse(Call> call, Response> resp) { super.onResponse(call, resp); @@ -62,7 +62,7 @@ public void onResponse(Call> call, Response> resp) { private void getSubscribers( String auth, Activity activity, Map mySubscriptions) { profileService.getMySubscribers(auth).enqueue( - new ActivityRecreatorOnAuthFailure<>(activity) { + new BaseOnNotAuthenticatedCallback<>(activity, activity::recreate) { @Override public void onResponse(Call> call, Response> resp) { super.onResponse(call, resp); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileSubscriptionsViewModel.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileSubscriptionsViewModel.java index 431818b..9adf60c 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileSubscriptionsViewModel.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileSubscriptionsViewModel.java @@ -11,7 +11,7 @@ import com.tom.meeter.context.network.dto.UserDTO; import com.tom.meeter.context.profile.service.ProfileService; import com.tom.meeter.context.profile.subscriber.Subscriber; -import com.tom.meeter.infrastructure.http.ActivityRecreatorOnAuthFailure; +import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; import com.tom.meeter.infrastructure.http.HttpCodes; import java.util.ArrayList; @@ -38,7 +38,7 @@ public ProfileSubscriptionsViewModel(ProfileService profileService) { public void fetchProfileSubscriptions(String auth, Activity activity) { profileService.getMySubscriptions(auth).enqueue( - new ActivityRecreatorOnAuthFailure<>(activity) { + new BaseOnNotAuthenticatedCallback<>(activity, activity::recreate) { @Override public void onResponse(Call> call, Response> resp) { super.onResponse(call, resp); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java index 2790483..77f693d 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java @@ -38,8 +38,8 @@ import com.tom.meeter.infrastructure.common.Globals; import com.tom.meeter.infrastructure.components.adapter.EventsCardAdapter; import com.tom.meeter.infrastructure.components.binder.PhotoDownloaderEventBinder; +import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; import com.tom.meeter.infrastructure.http.HttpCodes; -import com.tom.meeter.infrastructure.http.HttpErrorLogger; import java.time.LocalDate; @@ -124,7 +124,7 @@ private void onInit(String token) { } if (amISubscriber) { userService.unsubscribe(Globals.getAuthHeader(token), userId).enqueue( - new HttpErrorLogger<>(this) { + new BaseOnNotAuthenticatedCallback<>(this, this::recreate) { @Override public void onResponse(Call call, Response resp) { super.onResponse(call, resp); @@ -133,14 +133,11 @@ public void onResponse(Call call, Response resp) { showMessage(UserActivity.this, R.string.successfully_unsubscribed); return; } - if (resp.code() == HttpCodes.NOT_AUTHENTICATED) { - UserActivity.this.recreate(); - } } }); } else { userService.subscribe(Globals.getAuthHeader(token), userId).enqueue( - new HttpErrorLogger<>(this) { + new BaseOnNotAuthenticatedCallback<>(this, this::recreate) { @Override public void onResponse(Call call, Response resp) { super.onResponse(call, resp); @@ -149,9 +146,6 @@ public void onResponse(Call call, Response resp) { showMessage(UserActivity.this, R.string.successfully_subscribed); return; } - if (resp.code() == HttpCodes.NOT_AUTHENTICATED) { - UserActivity.this.recreate(); - } } }); } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserSubscribersViewModel.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserSubscribersViewModel.java index c1befe8..b585400 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserSubscribersViewModel.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserSubscribersViewModel.java @@ -10,7 +10,7 @@ import com.tom.meeter.context.network.dto.UserDTO; import com.tom.meeter.context.user.service.UserService; -import com.tom.meeter.infrastructure.http.ActivityRecreatorOnAuthFailure; +import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; import com.tom.meeter.infrastructure.http.HttpCodes; import java.util.List; @@ -36,7 +36,7 @@ public UserSubscribersViewModel(UserService userService) { public void fetchUserSubscribers(String auth, String userId, Activity activity) { userService.getSubscribers(auth, userId).enqueue( - new ActivityRecreatorOnAuthFailure<>(activity) { + new BaseOnNotAuthenticatedCallback<>(activity, activity::recreate) { @Override public void onResponse(Call> call, Response> resp) { super.onResponse(call, resp); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserSubscriptionsViewModel.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserSubscriptionsViewModel.java index b4c13b1..ca5db44 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserSubscriptionsViewModel.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserSubscriptionsViewModel.java @@ -10,7 +10,7 @@ import com.tom.meeter.context.network.dto.UserDTO; import com.tom.meeter.context.user.service.UserService; -import com.tom.meeter.infrastructure.http.ActivityRecreatorOnAuthFailure; +import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; import com.tom.meeter.infrastructure.http.HttpCodes; import java.util.List; @@ -36,7 +36,7 @@ public UserSubscriptionsViewModel(UserService userService) { public void fetchUserSubscriptions(String auth, String userId, Activity activity) { userService.getSubscriptions(auth, userId).enqueue( - new ActivityRecreatorOnAuthFailure<>(activity) { + new BaseOnNotAuthenticatedCallback<>(activity, activity::recreate) { @Override public void onResponse(Call> call, Response> resp) { super.onResponse(call, resp); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserViewModel.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserViewModel.java index 704b17c..26e8392 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserViewModel.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserViewModel.java @@ -13,7 +13,7 @@ import com.tom.meeter.context.network.dto.UserDTO; import com.tom.meeter.context.user.service.UserService; import com.tom.meeter.infrastructure.common.Globals; -import com.tom.meeter.infrastructure.http.ActivityRecreatorOnAuthFailure; +import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; import com.tom.meeter.infrastructure.http.HttpCodes; import java.util.List; @@ -46,7 +46,7 @@ public UserViewModel( public void fetchUserInformation(String token, String userId, Activity activity) { userService.getUser(Globals.getAuthHeader(token), userId).enqueue( - new ActivityRecreatorOnAuthFailure<>(activity) { + new BaseOnNotAuthenticatedCallback<>(activity, activity::recreate) { @Override public void onResponse(Call call, Response resp) { super.onResponse(call, resp); @@ -68,7 +68,7 @@ public void onResponse(Call call, Response resp) { ); userService.amISubscribed(Globals.getAuthHeader(token), userId).enqueue( - new ActivityRecreatorOnAuthFailure<>(activity) { + new BaseOnNotAuthenticatedCallback<>(activity, activity::recreate) { @Override public void onResponse(Call call, Response resp) { super.onResponse(call, resp); @@ -81,7 +81,7 @@ public void onResponse(Call call, Response resp) { ); userService.getUserEvents(Globals.getAuthHeader(token), userId).enqueue( - new ActivityRecreatorOnAuthFailure<>(activity) { + new BaseOnNotAuthenticatedCallback<>(activity, activity::recreate) { @Override public void onResponse(Call> call, Response> resp) { super.onResponse(call, resp); diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/http/ActivityRecreatorOnAuthFailure.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/http/ActivityRecreatorOnAuthFailure.java deleted file mode 100644 index 7bd74b0..0000000 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/http/ActivityRecreatorOnAuthFailure.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.tom.meeter.infrastructure.http; - -import android.app.Activity; -import android.util.Log; - -import retrofit2.Call; -import retrofit2.Response; - -public class ActivityRecreatorOnAuthFailure extends HttpErrorLogger { - - private static final String TAG = ActivityRecreatorOnAuthFailure.class.getCanonicalName(); - private final Activity activity; - - public ActivityRecreatorOnAuthFailure(Activity activity) { - super(activity.getApplicationContext()); - this.activity = activity; - } - - @Override - public void onResponse(Call call, Response response) { - super.onResponse(call, response); - if (response.code() == HttpCodes.NOT_AUTHENTICATED) { - Log.d(TAG, "Recreating: " + activity.getClass().getCanonicalName()); - activity.recreate(); - } - } -} diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/http/BaseOnNotAuthenticatedCallback.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/http/BaseOnNotAuthenticatedCallback.java new file mode 100644 index 0000000..a3e7e56 --- /dev/null +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/http/BaseOnNotAuthenticatedCallback.java @@ -0,0 +1,28 @@ +package com.tom.meeter.infrastructure.http; + +import android.content.Context; +import android.util.Log; + +import retrofit2.Call; +import retrofit2.Response; + +public class BaseOnNotAuthenticatedCallback extends HttpErrorLogger { + + private static final String TAG = BaseOnNotAuthenticatedCallback.class.getCanonicalName(); + + private final Runnable onNotAuthenticated; + + public BaseOnNotAuthenticatedCallback(Context ctx, Runnable onNotAuthenticated) { + super(ctx); + this.onNotAuthenticated = onNotAuthenticated; + } + + @Override + public void onResponse(Call call, Response resp) { + super.onResponse(call, resp); + if (resp.code() == HttpCodes.NOT_AUTHENTICATED) { + Log.d(TAG, "On auth fail for: " + ctx.getClass().getCanonicalName()); + onNotAuthenticated.run(); + } + } +} diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/http/DisconnectLogger.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/http/DisconnectLogger.java index 7e96068..a5ac13b 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/http/DisconnectLogger.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/http/DisconnectLogger.java @@ -16,7 +16,7 @@ public abstract class DisconnectLogger implements Callback { private static final String TAG = DisconnectLogger.class.getCanonicalName(); - private final Context ctx; + protected final Context ctx; public DisconnectLogger(Context ctx) { this.ctx = ctx; diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/http/ErrorLogger.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/http/ErrorLogger.java index 2e8e51e..7439e2f 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/http/ErrorLogger.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/http/ErrorLogger.java @@ -10,11 +10,8 @@ public abstract class ErrorLogger extends DisconnectLogger { private static final String TAG = ErrorLogger.class.getCanonicalName(); - private final Context ctx; - public ErrorLogger(Context ctx) { super(ctx); - this.ctx = ctx; } @Override diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/http/HttpErrorLogger.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/http/HttpErrorLogger.java index 8835884..7689827 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/http/HttpErrorLogger.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/http/HttpErrorLogger.java @@ -15,11 +15,8 @@ public class HttpErrorLogger extends ErrorLogger { private static final String TAG = HttpErrorLogger.class.getCanonicalName(); - private final Context ctx; - public HttpErrorLogger(Context ctx) { super(ctx); - this.ctx = ctx; } @Override From af5227a226cf40a9803f28aad47cfe8e3a7365fc Mon Sep 17 00:00:00 2001 From: Georgy Lebedik Date: Thu, 26 Jun 2025 15:12:18 +0300 Subject: [PATCH 06/32] Small refactoring. --- .../event/activity/ProfileEventActivity.java | 68 ++++++++++--------- .../event/activity/UserEventActivity.java | 13 ++-- .../event/viewmodel/EventViewModel.java | 9 ++- .../event/viewmodel/EventViewModelModule.java | 4 +- 4 files changed, 48 insertions(+), 46 deletions(-) diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/ProfileEventActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/ProfileEventActivity.java index 09d03a2..6628522 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/ProfileEventActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/ProfileEventActivity.java @@ -68,7 +68,7 @@ public class ProfileEventActivity extends AppCompatActivity { @Inject EventService eventService; @Inject - EventViewModel.EventViewModelAssistedFactory factory; + EventViewModel.AssistedFactory assistedFactory; @Inject ImageDownloader imgDownloader; @@ -93,35 +93,6 @@ public class ProfileEventActivity extends AppCompatActivity { binding.photoPath.setText(photoPath); }); - void downloadAndUpdateLayoutPhoto(String photoPath) { - imgDownloader.downloadEventImage(photoPath, this, - this::updateLayoutPhoto, ImagesHelper::bigCircleImage, - this::recreate); - } - - private void updateLayoutPhoto(Bitmap photo) { - photoCache = photo; - binding.photo.setImageBitmap(photoCache); - } - - private void switchEditMode() { - isEditableModeEnabled = !isEditableModeEnabled; - - binding.selectPhotoButton.setEnabled(isEditableModeEnabled); - binding.locationMapButton.setEnabled(isEditableModeEnabled); - binding.selectStartingDateButton.setEnabled(isEditableModeEnabled); - binding.selectEndingDateButton.setEnabled(isEditableModeEnabled); - - binding.name.setEnabled(isEditableModeEnabled); - binding.description.setEnabled(isEditableModeEnabled); - binding.latitude.setEnabled(isEditableModeEnabled); - binding.longitude.setEnabled(isEditableModeEnabled); - binding.starting.setEnabled(isEditableModeEnabled); - binding.ending.setEnabled(isEditableModeEnabled); - binding.city.setEnabled(isEditableModeEnabled); - binding.editSaveButton.setText(isEditableModeEnabled ? R.string.save : R.string.edit); - } - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -163,10 +134,12 @@ protected void onCreate(Bundle savedInstanceState) { } private void onInit(String token, String eventId) { - ViewModelProvider.Factory factory = EventViewModel.providesFactory( - this.factory, eventId, token, this, this::recreate); - viewModel = new ViewModelProvider(this, factory) + viewModel = new ViewModelProvider( + this, + EventViewModel.factory( + assistedFactory, eventId, token, this, this::recreate)) .get(EventViewModel.class); + initLayout(token); viewModel.getEvent() @@ -231,6 +204,35 @@ public void onResponse(Call call, Response resp) { new Intent(this, UploadEventImageActivity.class))); } + void downloadAndUpdateLayoutPhoto(String photoPath) { + imgDownloader.downloadEventImage(photoPath, this, + this::updateLayoutPhoto, ImagesHelper::bigCircleImage, + this::recreate); + } + + private void updateLayoutPhoto(Bitmap photo) { + photoCache = photo; + binding.photo.setImageBitmap(photoCache); + } + + private void switchEditMode() { + isEditableModeEnabled = !isEditableModeEnabled; + + binding.selectPhotoButton.setEnabled(isEditableModeEnabled); + binding.locationMapButton.setEnabled(isEditableModeEnabled); + binding.selectStartingDateButton.setEnabled(isEditableModeEnabled); + binding.selectEndingDateButton.setEnabled(isEditableModeEnabled); + + binding.name.setEnabled(isEditableModeEnabled); + binding.description.setEnabled(isEditableModeEnabled); + binding.latitude.setEnabled(isEditableModeEnabled); + binding.longitude.setEnabled(isEditableModeEnabled); + binding.starting.setEnabled(isEditableModeEnabled); + binding.ending.setEnabled(isEditableModeEnabled); + binding.city.setEnabled(isEditableModeEnabled); + binding.editSaveButton.setText(isEditableModeEnabled ? R.string.save : R.string.edit); + } + private void showAlertDialog() { new AlertDialog.Builder(this) .setTitle(R.string.delete_event) diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/UserEventActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/UserEventActivity.java index 6d2a897..4f653ec 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/UserEventActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/UserEventActivity.java @@ -6,7 +6,6 @@ import static com.tom.meeter.infrastructure.common.CommonHelper.UI_DATE_TIME_FORMAT; import static com.tom.meeter.infrastructure.common.CommonHelper.dateOrNull; import static com.tom.meeter.infrastructure.common.CommonHelper.textOrNull; -import static com.tom.meeter.infrastructure.common.ImagesHelper.circleImage; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; import android.accounts.AccountManager; @@ -41,9 +40,9 @@ public class UserEventActivity extends AppCompatActivity { @Inject EventService eventService; @Inject - EventViewModel.EventViewModelAssistedFactory factory; + EventViewModel.AssistedFactory assistedFactory; - ActivityEventReadableBinding binding; + private ActivityEventReadableBinding binding; private EventViewModel viewModel; private AccountManager accountManager; @@ -75,10 +74,12 @@ protected void onCreate(Bundle savedInstanceState) { } private void onInit(String token, String eventId) { - ViewModelProvider.Factory factory = EventViewModel.providesFactory( - this.factory, eventId, token, this, this::recreate); - viewModel = new ViewModelProvider(this, factory) + viewModel = new ViewModelProvider( + this, + EventViewModel.factory( + assistedFactory, eventId, token, this, this::recreate)) .get(EventViewModel.class); + viewModel.getEvent() .observe(this, event -> { String userUuid = AuthHelper.getUserUuid(accountManager); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModel.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModel.java index f6948da..4f51ac5 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModel.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModel.java @@ -20,7 +20,6 @@ import com.tom.meeter.infrastructure.http.HttpCodes; import dagger.assisted.Assisted; -import dagger.assisted.AssistedFactory; import dagger.assisted.AssistedInject; import retrofit2.Call; import retrofit2.Response; @@ -58,8 +57,8 @@ public EventViewModel( init(); } - @AssistedFactory - public interface EventViewModelAssistedFactory { + @dagger.assisted.AssistedFactory + public interface AssistedFactory { EventViewModel create( @Assisted(ASSISTED_EVENT) String eventId, @Assisted(ASSISTED_TOKEN) String token, @@ -67,8 +66,8 @@ EventViewModel create( @Assisted Runnable onNotAuthenticated); } - public static ViewModelProvider.Factory providesFactory( - EventViewModelAssistedFactory assistedFactory, + public static ViewModelProvider.Factory factory( + AssistedFactory assistedFactory, String eventId, String token, Context ctx, Runnable onNotAuthenticated) { return new ViewModelProvider.Factory() { diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModelModule.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModelModule.java index 94303ee..d085a5e 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModelModule.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModelModule.java @@ -10,7 +10,7 @@ public interface EventViewModelModule { ViewModel eventViewModel(EventViewModel eventViewModel);*/ /* @Binds - EventViewModel.EventViewModelAssistedFactory bindFactory( - EventViewModel.EventViewModelAssistedFactory impl + EventViewModel.AssistedFactory bindFactory( + EventViewModel.AssistedFactory impl );*/ } From 3eb95698710b37c7999923ef93b54e27673480a7 Mon Sep 17 00:00:00 2001 From: Georgy Lebedik Date: Thu, 26 Jun 2025 15:36:53 +0300 Subject: [PATCH 07/32] Small refactoring. --- .../auth/infrastructure/AuthHelper.java | 23 ++++++++----------- .../event/activity/ProfileEventActivity.java | 15 ++++++------ .../event/activity/UserEventActivity.java | 11 ++++----- .../tom/meeter/context/event/utils/Utils.java | 17 ++++++++++++++ 4 files changed, 39 insertions(+), 27 deletions(-) diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/auth/infrastructure/AuthHelper.java b/AndroidClient/src/main/java/com/tom/meeter/context/auth/infrastructure/AuthHelper.java index 4740ed4..624111f 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/auth/infrastructure/AuthHelper.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/auth/infrastructure/AuthHelper.java @@ -18,9 +18,8 @@ import com.tom.meeter.R; import com.tom.meeter.context.token.service.TokenService; import com.tom.meeter.infrastructure.common.Globals; -import com.tom.meeter.infrastructure.http.ErrorLogger; +import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; import com.tom.meeter.infrastructure.http.HttpCodes; -import com.tom.meeter.infrastructure.http.HttpErrorLogger; import java.io.IOException; import java.util.function.Consumer; @@ -102,12 +101,12 @@ private static void simpleCheckToken( Consumer onToken, Runnable onCancelledAuth) { tokenService.checkToken(Globals.getAuthHeader(token)).enqueue( - new ErrorLogger<>(activity) { + new BaseOnNotAuthenticatedCallback<>( + activity, + () -> invalidateToken(am, activity, onToken, onCancelledAuth)) { @Override public void onResponse(Call call, Response response) { - if (response.code() == HttpCodes.NOT_AUTHENTICATED) { - invalidateToken(am, activity, onToken, onCancelledAuth); - } + super.onResponse(call, response); if (response.code() == HttpCodes.OK) { onToken.accept(token); } @@ -124,7 +123,9 @@ private static void checkTokenWithRetry( Runnable onCancelledAuth, int attempt) { tokenService.checkToken(Globals.getAuthHeader(token)) - .enqueue(new HttpErrorLogger<>(activity) { + .enqueue(new BaseOnNotAuthenticatedCallback<>( + activity, + () -> invalidateToken(am, activity, onToken, onCancelledAuth)) { @Override public void onResponse(Call call, Response resp) { super.onResponse(call, resp); @@ -132,10 +133,6 @@ public void onResponse(Call call, Response resp) { onToken.accept(token); return; } - if (resp.code() == HttpCodes.NOT_AUTHENTICATED) { - invalidateToken(am, activity, onToken, onCancelledAuth); - return; - } } @Override @@ -149,7 +146,7 @@ public void onFailure(Call call, Throwable t) { private void retryIfPossible() { if (attempt < MAX_RETRIES) { - Log.w(TAG, "Повтор попытки " + (attempt + 1)); + Log.w(TAG, "Retry: " + (attempt + 1)); new Handler(Looper.getMainLooper()) .postDelayed( () -> checkTokenWithRetry( @@ -157,7 +154,7 @@ private void retryIfPossible() { onCancelledAuth, attempt + 1), RETRY_DELAY_MS); } else { - Log.e(TAG, "Превышено количество попыток"); + Log.e(TAG, "Exceeded retry count."); } } }); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/ProfileEventActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/ProfileEventActivity.java index 6628522..f89f03e 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/ProfileEventActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/ProfileEventActivity.java @@ -5,6 +5,8 @@ import static com.tom.meeter.context.event.activity.EventDispatcherActivity.EVENT_ID_KEY; import static com.tom.meeter.context.event.activity.EventLocationMapActivity.createEventLocationMapActivityIntent; import static com.tom.meeter.context.event.utils.Utils.createUpdateEventRequest; +import static com.tom.meeter.context.event.utils.Utils.currentUserIsEventCreator; +import static com.tom.meeter.context.event.utils.Utils.dumpEventDispatcherError; import static com.tom.meeter.context.image.activity.BaseUploadActivity.PHOTO_PATH_RESULT; import static com.tom.meeter.infrastructure.common.CommonHelper.UI_DATE_TIME_FORMAT; import static com.tom.meeter.infrastructure.common.CommonHelper.dateOrNull; @@ -33,7 +35,6 @@ import com.tom.meeter.App; import com.tom.meeter.R; -import com.tom.meeter.context.auth.infrastructure.AuthHelper; import com.tom.meeter.context.event.message.UpdateEventRequest; import com.tom.meeter.context.event.service.EventService; import com.tom.meeter.context.event.viewmodel.EventViewModel; @@ -144,18 +145,16 @@ private void onInit(String token, String eventId) { viewModel.getEvent() .observe(this, event -> { - String userUuid = AuthHelper.getUserUuid(accountManager); - String eventCreatorId = event.getCreatorId(); - if (!userUuid.equals(eventCreatorId)) { - Log.e(TAG, "Profile event activity for non creator " - + userUuid + "/" + eventId + " : " + eventCreatorId); + if (!currentUserIsEventCreator(accountManager, event)) { + dumpEventDispatcherError(TAG, accountManager, event); finish(); + return; } eventCache = event; updateLayout(); + viewModel.getEventPhoto() + .observe(this, this::updateLayoutPhoto); }); - viewModel.getEventPhoto() - .observe(this, this::updateLayoutPhoto); } private void initLayout(String token) { diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/UserEventActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/UserEventActivity.java index 4f653ec..16889cd 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/UserEventActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/UserEventActivity.java @@ -2,6 +2,8 @@ import static com.tom.meeter.context.auth.infrastructure.AuthHelper.checkToken; import static com.tom.meeter.context.event.activity.EventOnMapActivity.dispatchToEventOnMapActivity; +import static com.tom.meeter.context.event.utils.Utils.currentUserIsEventCreator; +import static com.tom.meeter.context.event.utils.Utils.dumpEventDispatcherError; import static com.tom.meeter.context.user.activity.UserActivity.dispatchToUserActivity; import static com.tom.meeter.infrastructure.common.CommonHelper.UI_DATE_TIME_FORMAT; import static com.tom.meeter.infrastructure.common.CommonHelper.dateOrNull; @@ -22,7 +24,6 @@ import androidx.lifecycle.ViewModelProvider; import com.tom.meeter.App; -import com.tom.meeter.context.auth.infrastructure.AuthHelper; import com.tom.meeter.context.event.service.EventService; import com.tom.meeter.context.event.viewmodel.EventViewModel; import com.tom.meeter.context.network.dto.EventDTO; @@ -82,12 +83,10 @@ private void onInit(String token, String eventId) { viewModel.getEvent() .observe(this, event -> { - String userUuid = AuthHelper.getUserUuid(accountManager); - String eventCreatorId = event.getCreatorId(); - if (userUuid.equals(eventCreatorId)) { - Log.e(TAG, "User event activity for" + - " creator " + userUuid + "/" + eventId + " : " + eventCreatorId); + if (currentUserIsEventCreator(accountManager, event)) { + dumpEventDispatcherError(TAG, accountManager, event); finish(); + return; } initLayout(event); viewModel.getEventPhoto() diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/utils/Utils.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/utils/Utils.java index 28bc06a..8d1d87b 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/utils/Utils.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/utils/Utils.java @@ -4,6 +4,10 @@ import static com.tom.meeter.infrastructure.common.CommonHelper.getOffsetDateTime; import static com.tom.meeter.infrastructure.common.CommonHelper.getStringOrNull; +import android.accounts.AccountManager; +import android.util.Log; + +import com.tom.meeter.context.auth.infrastructure.AuthHelper; import com.tom.meeter.context.event.message.UpdateEventRequest; import com.tom.meeter.context.network.dto.EventDTO; import com.tom.meeter.databinding.ActivityEventEditableBinding; @@ -54,4 +58,17 @@ public static UpdateEventRequest createUpdateEventRequest( } return req; } + + public static boolean currentUserIsEventCreator( + AccountManager am, EventDTO event) { + return AuthHelper.getUserUuid(am).equals(event.getCreatorId()); + } + + public static void dumpEventDispatcherError( + String tag, AccountManager am, EventDTO event) { + Log.e(tag, "System error. EventDispatcher did wrong dispatching. " + + "Current user is [" + AuthHelper.getUserUuid(am) + "], " + + "eventId [" + event.getId() + "], eventCreatorId [" + event.getCreatorId() + "]. " + + "Please, check server code and related entities."); + } } From f91a5f33d021391bb7e9a29abee569a102267017 Mon Sep 17 00:00:00 2001 From: Georgy Lebedik Date: Thu, 26 Jun 2025 16:43:13 +0300 Subject: [PATCH 08/32] Profile assisted factory, not full covered. --- .../meeter/context/event/EventComponent.java | 4 +- .../event/activity/ProfileEventActivity.java | 4 +- .../event/factory/EventViewModelFactory.java | 48 -------- .../event/viewmodel/EventViewModelModule.java | 16 --- .../meeter/context/image/ImageDownloader.java | 35 +++++- .../profile/factory/AssistedFactoryBase.java | 10 ++ ...ProfileEventsViewModelAssistedFactory.java | 10 ++ .../ProfileViewModelAssistedFactory.java | 10 ++ .../fragment/ProfileEventsFragment.java | 23 ++-- .../profile/fragment/ProfileFragment.java | 49 ++++----- .../viewmodel/ProfileEventsViewModel.java | 62 ++++++++--- .../profile/viewmodel/ProfileViewModel.java | 104 +++++++++++------- .../meeter/context/user/UserComponent.java | 1 - .../{viewmodel => }/UserViewModelModule.java | 5 +- .../context/user/activity/UserActivity.java | 2 +- .../user/factory/UserViewModelFactory.java | 2 +- .../context/user/viewmodel/UserViewModel.java | 9 +- .../injection/viewmodel/ViewModelModule.java | 6 +- 18 files changed, 226 insertions(+), 174 deletions(-) delete mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/event/factory/EventViewModelFactory.java delete mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModelModule.java create mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/AssistedFactoryBase.java create mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileEventsViewModelAssistedFactory.java create mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileViewModelAssistedFactory.java rename AndroidClient/src/main/java/com/tom/meeter/context/user/{viewmodel => }/UserViewModelModule.java (74%) diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/EventComponent.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/EventComponent.java index 8933210..bbd65e3 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/EventComponent.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/EventComponent.java @@ -13,9 +13,7 @@ import dagger.Component; @EventScope -@Component( -/* modules = {EventViewModelModule.class},*/ - dependencies = {AppComponent.class}) +@Component(dependencies = {AppComponent.class}) public interface EventComponent { @Component.Builder diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/ProfileEventActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/ProfileEventActivity.java index f89f03e..5f6bdc0 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/ProfileEventActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/ProfileEventActivity.java @@ -79,7 +79,6 @@ public class ProfileEventActivity extends AppCompatActivity { private ActivityResultLauncher mapResult; private EventDTO eventCache; - private Bitmap photoCache; private boolean isEditableModeEnabled = false; private final ActivityResultLauncher imageUploadLauncher = @@ -210,8 +209,7 @@ void downloadAndUpdateLayoutPhoto(String photoPath) { } private void updateLayoutPhoto(Bitmap photo) { - photoCache = photo; - binding.photo.setImageBitmap(photoCache); + binding.photo.setImageBitmap(photo); } private void switchEditMode() { diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/factory/EventViewModelFactory.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/factory/EventViewModelFactory.java deleted file mode 100644 index 0ce7434..0000000 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/factory/EventViewModelFactory.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.tom.meeter.context.event.factory; - -import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; - -import android.util.Log; - -import androidx.lifecycle.ViewModel; -import androidx.lifecycle.ViewModelProvider; - -import com.tom.meeter.context.event.EventScope; -import com.tom.meeter.context.user.viewmodel.UserViewModelModule; - -import java.util.Map; - -import javax.inject.Inject; -import javax.inject.Provider; - -@EventScope -public class EventViewModelFactory implements ViewModelProvider.Factory { - - private static final String TAG = EventViewModelFactory.class.getCanonicalName(); - - private final Map, Provider> viewModels; - - @Inject - public EventViewModelFactory(Map, Provider> viewModels) { - logMethod(TAG, this); - this.viewModels = viewModels; - } - - @Override - public T create(Class modelClass) { - Log.d(TAG, "EventViewModelFactory creates " + modelClass); - - Provider viewModelProvider = viewModels.get(modelClass); - - if (viewModelProvider == null) { - throw new IllegalArgumentException("ViewModel class " + modelClass - + " not found. Check " + UserViewModelModule.class.getCanonicalName() - + " file to be properly aligned."); - } - Log.d(TAG, "Before viewModelProvider.get() " + modelClass); - T t = (T) viewModelProvider.get(); - Log.d(TAG, "After viewModelProvider.get()" + modelClass); - - return t; - } -} diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModelModule.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModelModule.java deleted file mode 100644 index d085a5e..0000000 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModelModule.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.tom.meeter.context.event.viewmodel; - -import dagger.Module; - -@Module -public interface EventViewModelModule { -/* @Binds - @IntoMap - @ViewModelKey(EventViewModel.class) - ViewModel eventViewModel(EventViewModel eventViewModel);*/ - -/* @Binds - EventViewModel.AssistedFactory bindFactory( - EventViewModel.AssistedFactory impl - );*/ -} diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/image/ImageDownloader.java b/AndroidClient/src/main/java/com/tom/meeter/context/image/ImageDownloader.java index 1dd3875..19865e6 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/image/ImageDownloader.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/image/ImageDownloader.java @@ -33,7 +33,8 @@ public ImageDownloader(ImageService imageService) { public void downloadEventImage( String photoPath, Context ctx, - Consumer onDownloaded, Function bodyConverter, + Consumer onDownloaded, + Function bodyConverter, Runnable onNotAuthenticated) { imageService.downloadEventImage(getAuthHeader(AccountManager.get(ctx)), photoPath) .enqueue(new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { @@ -41,11 +42,12 @@ public void downloadEventImage( public void onResponse(Call call, Response response) { super.onResponse(call, response); //Log.d(TAG, "/images/event" + photoPath + " downloaded..."); - if (response.code() == HttpCodes.OK) { - try (ResponseBody body = response.body()) { - onDownloaded.accept(bodyConverter.apply(body)); - return; - } + if (response.code() != HttpCodes.OK) { + return; + } + try (ResponseBody body = response.body()) { + onDownloaded.accept(bodyConverter.apply(body)); + return; } } }); @@ -89,4 +91,25 @@ public void onResponse(Call call, Response response) } }); } + + public void downloadUserImage( + String photoPath, Context ctx, + Function converter, + Consumer onDownloaded, + Runnable onNotAuthenticated) { + imageService.downloadUserImage(getAuthHeader(AccountManager.get(ctx)), photoPath) + .enqueue(new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { + @Override + public void onResponse(Call call, Response resp) { + super.onResponse(call, resp); + if (resp.code() != HttpCodes.OK) { + return; + } + try (ResponseBody body = resp.body()) { + onDownloaded.accept(converter.apply(body)); + return; + } + } + }); + } } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/AssistedFactoryBase.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/AssistedFactoryBase.java new file mode 100644 index 0000000..45dca10 --- /dev/null +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/AssistedFactoryBase.java @@ -0,0 +1,10 @@ +package com.tom.meeter.context.profile.factory; + +import android.content.Context; + +import androidx.lifecycle.ViewModel; + +public interface AssistedFactoryBase { + + T create(String auth, Context ctx, Runnable onNotAuthenticated); +} diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileEventsViewModelAssistedFactory.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileEventsViewModelAssistedFactory.java new file mode 100644 index 0000000..338aa09 --- /dev/null +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileEventsViewModelAssistedFactory.java @@ -0,0 +1,10 @@ +package com.tom.meeter.context.profile.factory; + +import com.tom.meeter.context.profile.viewmodel.ProfileEventsViewModel; + +import dagger.assisted.AssistedFactory; + +@AssistedFactory +public interface ProfileEventsViewModelAssistedFactory + extends AssistedFactoryBase { +} diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileViewModelAssistedFactory.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileViewModelAssistedFactory.java new file mode 100644 index 0000000..2cc078b --- /dev/null +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileViewModelAssistedFactory.java @@ -0,0 +1,10 @@ +package com.tom.meeter.context.profile.factory; + +import com.tom.meeter.context.profile.viewmodel.ProfileViewModel; + +import dagger.assisted.AssistedFactory; + +@AssistedFactory +public interface ProfileViewModelAssistedFactory + extends AssistedFactoryBase { +} diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileEventsFragment.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileEventsFragment.java index a3ad1f6..56e19f2 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileEventsFragment.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileEventsFragment.java @@ -14,17 +14,17 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; -import androidx.lifecycle.ViewModelProviders; +import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.LinearLayoutManager; import com.tom.meeter.App; import com.tom.meeter.context.image.ImageDownloader; import com.tom.meeter.context.profile.adapter.EventsAdapter; +import com.tom.meeter.context.profile.factory.ProfileEventsViewModelAssistedFactory; import com.tom.meeter.context.profile.viewmodel.ProfileEventsViewModel; import com.tom.meeter.databinding.SubFragmentUserEventsBinding; import com.tom.meeter.infrastructure.common.InfrastructureHelper; import com.tom.meeter.infrastructure.components.binder.PhotoDownloaderWithCacheEventBinder; -import com.tom.meeter.infrastructure.injection.viewmodel.ViewModelFactory; import javax.inject.Inject; @@ -37,11 +37,11 @@ public class ProfileEventsFragment extends Fragment { private EventsAdapter adapter; @Inject - ViewModelFactory viewModelFactory; + ProfileEventsViewModelAssistedFactory assistedFactory; @Inject ImageDownloader imageDownloader; - private ProfileEventsViewModel profileEventsViewModel; + private ProfileEventsViewModel viewModel; private AccountManager accountManager; @@ -83,13 +83,20 @@ public View onCreateView( public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); logMethod(TAG, this); - profileEventsViewModel = ViewModelProviders.of(this, viewModelFactory) + + String auth = getAuthHeader(accountManager); + viewModel = new ViewModelProvider( + this, + ProfileEventsViewModel.factory( + assistedFactory, auth, requireContext(), + () -> InfrastructureHelper.restartActivityFromFragment(this))) .get(ProfileEventsViewModel.class); - profileEventsViewModel.fetchProfileEvents(getAuthHeader(accountManager), this); - profileEventsViewModel.getProfileEventsLiveData() - .observe(getViewLifecycleOwner(), events -> adapter.setData(events)); + binding.userEventsFragmentRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); binding.userEventsFragmentRecyclerView.setAdapter(adapter); + + viewModel.getEvents() + .observe(getViewLifecycleOwner(), events -> adapter.setData(events)); } @Override diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileFragment.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileFragment.java index d15e021..4561915 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileFragment.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileFragment.java @@ -8,7 +8,6 @@ import static com.tom.meeter.infrastructure.common.CommonHelper.getLocalDateOrNull; import static com.tom.meeter.infrastructure.common.CommonHelper.getStringOrNull; import static com.tom.meeter.infrastructure.common.DateHelper.getAgeFromDate; -import static com.tom.meeter.infrastructure.common.ImagesHelper.circleImage; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.showMessage; @@ -16,6 +15,7 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; +import android.graphics.Bitmap; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; @@ -37,23 +37,23 @@ import com.tom.meeter.context.network.dto.UserDTO; import com.tom.meeter.context.profile.activity.SubscribersActivity; import com.tom.meeter.context.profile.activity.SubscriptionsActivity; +import com.tom.meeter.context.profile.factory.ProfileViewModelAssistedFactory; import com.tom.meeter.context.profile.message.UpdateProfileRequest; import com.tom.meeter.context.profile.service.ProfileService; import com.tom.meeter.context.profile.viewmodel.ProfileViewModel; import com.tom.meeter.databinding.FragmentProfileBinding; +import com.tom.meeter.infrastructure.common.ImagesHelper; import com.tom.meeter.infrastructure.common.InfrastructureHelper; import com.tom.meeter.infrastructure.components.adapter.EventsCardAdapter; import com.tom.meeter.infrastructure.components.binder.PhotoDownloaderEventBinder; import com.tom.meeter.infrastructure.http.ActivityRestarterOnAuthFailure; import com.tom.meeter.infrastructure.http.HttpCodes; -import com.tom.meeter.infrastructure.injection.viewmodel.ViewModelFactory; import java.time.LocalDate; import java.util.Objects; import javax.inject.Inject; -import okhttp3.ResponseBody; import retrofit2.Call; import retrofit2.Response; @@ -63,22 +63,20 @@ public class ProfileFragment extends Fragment { private static final String TAG = ProfileFragment.class.getCanonicalName(); - private boolean isEditableModeEnabled = false; - - private FragmentProfileBinding binding; @Inject - ViewModelFactory viewModelFactory; + ProfileViewModelAssistedFactory assistedFactory; @Inject ImageDownloader imageDownloader; @Inject ProfileService profileService; - private ProfileViewModel profileViewModel; + private AccountManager accountManager; private EventsCardAdapter adapter; - + private FragmentProfileBinding binding; + private ProfileViewModel viewModel; + private boolean isEditableModeEnabled = false; private UserDTO userCache; - private ResponseBody photoCache; public ProfileFragment() { logMethod(TAG, this); @@ -124,14 +122,16 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat super.onViewCreated(view, savedInstanceState); logMethod(TAG, this); - profileViewModel = new ViewModelProvider(this, viewModelFactory) + String auth = getAuthHeader(accountManager); + viewModel = new ViewModelProvider( + this, + ProfileViewModel.factory( + assistedFactory, auth, requireContext(), + () -> InfrastructureHelper.restartActivityFromFragment(this))) .get(ProfileViewModel.class); - String authHeader = getAuthHeader(accountManager); - - profileViewModel.fetchProfile(authHeader, this); LifecycleOwner owner = getViewLifecycleOwner(); - profileViewModel.getProfileLiveData() + viewModel.getProfile() .observe( owner, user -> { @@ -139,14 +139,14 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat updateLayoutValues(); }); - profileViewModel.getProfileEventsLiveData() - .observe(owner, events -> adapter.setData(events)); - profileViewModel.getProfilePhotoLiveData() - .observe(owner, this::updateLayoutPhoto); - binding.events.setLayoutManager(new GridLayoutManager(getContext(), 2)); binding.events.setAdapter(adapter); + viewModel.getEvents() + .observe(owner, events -> adapter.setData(events)); + viewModel.getPhoto() + .observe(owner, this::updateLayoutPhoto); + binding.btnEdit.setOnClickListener(v -> { if (isEditableModeEnabled) { UpdateProfileRequest req = createUpdateProfileRequest(); @@ -155,7 +155,7 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat switchEditMode(); return; } - profileService.updateProfile(authHeader, req) + profileService.updateProfile(auth, req) .enqueue(new ActivityRestarterOnAuthFailure<>(this) { @Override public void onResponse(Call call, Response response) { @@ -201,13 +201,12 @@ private void updateLayoutValues() { void downloadAndUpdateLayoutPhoto(String photoPath) { imageDownloader.downloadUserImage(photoPath, requireContext(), - this::updateLayoutPhoto, + ImagesHelper::bigCircleImage, this::updateLayoutPhoto, () -> InfrastructureHelper.restartActivityFromFragment(this)); } - private void updateLayoutPhoto(ResponseBody photo) { - photoCache = photo; - binding.photo.setImageBitmap(circleImage(photoCache, 600, 600)); + private void updateLayoutPhoto(Bitmap photo) { + binding.photo.setImageBitmap(photo); } private void switchEditMode() { diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileEventsViewModel.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileEventsViewModel.java index fc2c6d5..cdf1a0b 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileEventsViewModel.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileEventsViewModel.java @@ -2,20 +2,23 @@ import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; -import androidx.fragment.app.Fragment; +import android.content.Context; + import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.ViewModel; +import androidx.lifecycle.ViewModelProvider; import com.tom.meeter.context.network.dto.EventDTO; +import com.tom.meeter.context.profile.factory.ProfileEventsViewModelAssistedFactory; import com.tom.meeter.context.profile.service.ProfileService; -import com.tom.meeter.infrastructure.http.ActivityRestarterOnAuthFailure; +import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; import com.tom.meeter.infrastructure.http.HttpCodes; import java.util.List; -import javax.inject.Inject; - +import dagger.assisted.Assisted; +import dagger.assisted.AssistedInject; import retrofit2.Call; import retrofit2.Response; @@ -23,26 +26,51 @@ public class ProfileEventsViewModel extends ViewModel { private static final String TAG = ProfileEventsViewModel.class.getCanonicalName(); - private final MutableLiveData> profileEventsLiveData = new MutableLiveData<>(); + private final String auth; + private final Context ctx; + private final Runnable onNotAuthenticated; - private final ProfileService profileService; + private final MutableLiveData> events = new MutableLiveData<>(); + private final ProfileService service; - @Inject - public ProfileEventsViewModel(ProfileService profileService) { + @AssistedInject + public ProfileEventsViewModel( + ProfileService service, + @Assisted String auth, + @Assisted Context ctx, + @Assisted Runnable onNotAuthenticated) { logMethod(TAG, this); - this.profileService = profileService; + this.service = service; + this.auth = auth; + this.ctx = ctx.getApplicationContext(); + this.onNotAuthenticated = onNotAuthenticated; + init(); + } + + public static ViewModelProvider.Factory factory( + ProfileEventsViewModelAssistedFactory assistedFactory, + String auth, Context ctx, Runnable onNotAuthenticated) { + return new ViewModelProvider.Factory() { + @Override + @SuppressWarnings("unchecked") + public T create(Class modelClass) { + return (T) assistedFactory.create(auth, ctx, onNotAuthenticated); + } + }; } - public void fetchProfileEvents(String auth, Fragment fragment) { - profileService.getProfileEvents(auth).enqueue( - new ActivityRestarterOnAuthFailure<>(fragment) { + public void init() { + service.getProfileEvents(auth).enqueue( + new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { @Override - public void onResponse(Call> call, Response> response) { + public void onResponse( + Call> call, Response> response) { super.onResponse(call, response); - if (response.code() == HttpCodes.OK && response.body() != null) { - profileEventsLiveData.setValue(response.body()); + if (response.code() != HttpCodes.OK || response.body() == null) { return; } + events.setValue(response.body()); + return; } } ); @@ -54,7 +82,7 @@ protected void onCleared() { super.onCleared(); } - public LiveData> getProfileEventsLiveData() { - return profileEventsLiveData; + public LiveData> getEvents() { + return events; } } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileViewModel.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileViewModel.java index e9de605..ff11f12 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileViewModel.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileViewModel.java @@ -2,24 +2,27 @@ import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; -import androidx.fragment.app.Fragment; +import android.content.Context; +import android.graphics.Bitmap; + import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.ViewModel; +import androidx.lifecycle.ViewModelProvider; import com.tom.meeter.context.image.ImageDownloader; import com.tom.meeter.context.network.dto.EventDTO; import com.tom.meeter.context.network.dto.UserDTO; +import com.tom.meeter.context.profile.factory.ProfileViewModelAssistedFactory; import com.tom.meeter.context.profile.service.ProfileService; -import com.tom.meeter.infrastructure.common.InfrastructureHelper; -import com.tom.meeter.infrastructure.http.ActivityRestarterOnAuthFailure; +import com.tom.meeter.infrastructure.common.ImagesHelper; +import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; import com.tom.meeter.infrastructure.http.HttpCodes; import java.util.List; -import javax.inject.Inject; - -import okhttp3.ResponseBody; +import dagger.assisted.Assisted; +import dagger.assisted.AssistedInject; import retrofit2.Call; import retrofit2.Response; @@ -27,52 +30,79 @@ public class ProfileViewModel extends ViewModel { private static final String TAG = ProfileViewModel.class.getCanonicalName(); - private final MutableLiveData profileLiveData = new MutableLiveData<>(); - private final MutableLiveData profilePhotoLiveData = new MutableLiveData<>(); - private final MutableLiveData> profileEventsLiveData = new MutableLiveData<>(); + private final MutableLiveData profile = new MutableLiveData<>(); + private final MutableLiveData photo = new MutableLiveData<>(); + private final MutableLiveData> events = new MutableLiveData<>(); private final ProfileService profileService; private final ImageDownloader imageDownloader; - @Inject + private final String auth; + private final Context ctx; + private final Runnable onNotAuthenticated; + + @AssistedInject public ProfileViewModel( - ProfileService profileService, ImageDownloader imageDownloader) { + ProfileService profileService, ImageDownloader imageDownloader, + @Assisted String auth, + @Assisted Context ctx, + @Assisted Runnable onNotAuthenticated) { logMethod(TAG, this); this.profileService = profileService; this.imageDownloader = imageDownloader; + this.auth = auth; + this.ctx = ctx.getApplicationContext(); + this.onNotAuthenticated = onNotAuthenticated; + init(); } - public void fetchProfile(String auth, Fragment fragment) { + public static ViewModelProvider.Factory factory( + ProfileViewModelAssistedFactory assistedFactory, + String auth, Context ctx, Runnable onNotAuthenticated) { + return new ViewModelProvider.Factory() { + @Override + @SuppressWarnings("unchecked") + public T create(Class modelClass) { + return (T) assistedFactory.create(auth, ctx, onNotAuthenticated); + } + }; + } + + public void init() { profileService.getProfile(auth).enqueue( - new ActivityRestarterOnAuthFailure<>(fragment) { + new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { @Override - public void onResponse(Call call, Response response) { - super.onResponse(call, response); - if (response.code() == HttpCodes.OK) { - UserDTO user = response.body(); - profileLiveData.setValue(user); - String photoPath = user.getPhotoPath(); - if (photoPath == null) { - return; - } - imageDownloader.downloadUserImage( - photoPath, fragment.getContext(), - profilePhotoLiveData::setValue, - () -> InfrastructureHelper.restartActivityFromFragment(fragment)); + public void onResponse(Call call, Response resp) { + super.onResponse(call, resp); + if (resp.code() != HttpCodes.OK) { + return; + } + UserDTO user = resp.body(); + profile.setValue(user); + String photoPath = user.getPhotoPath(); + if (photoPath == null) { return; } + imageDownloader.downloadUserImage( + photoPath, ctx, + ImagesHelper::bigCircleImage, + photo::setValue, + onNotAuthenticated); + return; } } ); profileService.getProfileEvents(auth).enqueue( - new ActivityRestarterOnAuthFailure<>(fragment) { + new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { @Override - public void onResponse(Call> call, Response> response) { - super.onResponse(call, response); - if (response.code() == HttpCodes.OK && response.body() != null) { - profileEventsLiveData.setValue(response.body()); + public void onResponse( + Call> call, Response> resp) { + super.onResponse(call, resp); + if (resp.code() != HttpCodes.OK || resp.body() == null) { return; } + events.setValue(resp.body()); + return; } } ); @@ -84,15 +114,15 @@ protected void onCleared() { super.onCleared(); } - public LiveData getProfileLiveData() { - return profileLiveData; + public LiveData getProfile() { + return profile; } - public LiveData> getProfileEventsLiveData() { - return profileEventsLiveData; + public LiveData> getEvents() { + return events; } - public LiveData getProfilePhotoLiveData() { - return profilePhotoLiveData; + public LiveData getPhoto() { + return photo; } } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/UserComponent.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/UserComponent.java index 4a9f2aa..754430e 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/UserComponent.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/UserComponent.java @@ -6,7 +6,6 @@ import com.tom.meeter.context.user.activity.UserActivity; import com.tom.meeter.context.user.activity.UserSubscribersActivity; import com.tom.meeter.context.user.activity.UserSubscriptionsActivity; -import com.tom.meeter.context.user.viewmodel.UserViewModelModule; import dagger.BindsInstance; import dagger.Component; diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserViewModelModule.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/UserViewModelModule.java similarity index 74% rename from AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserViewModelModule.java rename to AndroidClient/src/main/java/com/tom/meeter/context/user/UserViewModelModule.java index 8110188..6bd8210 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserViewModelModule.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/UserViewModelModule.java @@ -1,7 +1,10 @@ -package com.tom.meeter.context.user.viewmodel; +package com.tom.meeter.context.user; import androidx.lifecycle.ViewModel; +import com.tom.meeter.context.user.viewmodel.UserSubscribersViewModel; +import com.tom.meeter.context.user.viewmodel.UserSubscriptionsViewModel; +import com.tom.meeter.context.user.viewmodel.UserViewModel; import com.tom.meeter.infrastructure.injection.viewmodel.ViewModelKey; import dagger.Binds; diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java index 77f693d..979e72d 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java @@ -153,7 +153,7 @@ public void onResponse(Call call, Response resp) { userViewModel = new ViewModelProvider(this, viewModelFactory) .get(UserViewModel.class); - userViewModel.fetchUserInformation(token, userId, this); + userViewModel.fetchUserInformation(Globals.getAuthHeader(token), userId, this); userViewModel.getUserLiveData() .observe(this, user -> { binding.name.setText(user.getName()); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserViewModelFactory.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserViewModelFactory.java index 54f47d7..8b29e9b 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserViewModelFactory.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserViewModelFactory.java @@ -8,7 +8,7 @@ import androidx.lifecycle.ViewModelProvider; import com.tom.meeter.context.user.UserScope; -import com.tom.meeter.context.user.viewmodel.UserViewModelModule; +import com.tom.meeter.context.user.UserViewModelModule; import java.util.Map; diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserViewModel.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserViewModel.java index 26e8392..83ea792 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserViewModel.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserViewModel.java @@ -12,7 +12,6 @@ import com.tom.meeter.context.network.dto.EventDTO; import com.tom.meeter.context.network.dto.UserDTO; import com.tom.meeter.context.user.service.UserService; -import com.tom.meeter.infrastructure.common.Globals; import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; import com.tom.meeter.infrastructure.http.HttpCodes; @@ -44,8 +43,8 @@ public UserViewModel( this.userService = userService; } - public void fetchUserInformation(String token, String userId, Activity activity) { - userService.getUser(Globals.getAuthHeader(token), userId).enqueue( + public void fetchUserInformation(String auth, String userId, Activity activity) { + userService.getUser(auth, userId).enqueue( new BaseOnNotAuthenticatedCallback<>(activity, activity::recreate) { @Override public void onResponse(Call call, Response resp) { @@ -67,7 +66,7 @@ public void onResponse(Call call, Response resp) { } ); - userService.amISubscribed(Globals.getAuthHeader(token), userId).enqueue( + userService.amISubscribed(auth, userId).enqueue( new BaseOnNotAuthenticatedCallback<>(activity, activity::recreate) { @Override public void onResponse(Call call, Response resp) { @@ -80,7 +79,7 @@ public void onResponse(Call call, Response resp) { } ); - userService.getUserEvents(Globals.getAuthHeader(token), userId).enqueue( + userService.getUserEvents(auth, userId).enqueue( new BaseOnNotAuthenticatedCallback<>(activity, activity::recreate) { @Override public void onResponse(Call> call, Response> resp) { diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/injection/viewmodel/ViewModelModule.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/injection/viewmodel/ViewModelModule.java index 95f80d6..757f4f3 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/injection/viewmodel/ViewModelModule.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/injection/viewmodel/ViewModelModule.java @@ -22,15 +22,17 @@ public ViewModelModule() { Log.d(TAG, "Configuring ViewModelModule..."); } - @Binds +/* @Binds @IntoMap @ViewModelKey(ProfileViewModel.class) - abstract ViewModel profileViewModel(ProfileViewModel profileViewModel); + abstract ViewModel profileViewModel(ProfileViewModel profileViewModel);*/ +/* @Binds @IntoMap @ViewModelKey(ProfileEventsViewModel.class) abstract ViewModel profileEventsViewModel(ProfileEventsViewModel profileEventsViewModel); +*/ @Binds @IntoMap From aca03af71b4a5495feacc6e12542425cf80ea7b0 Mon Sep 17 00:00:00 2001 From: Georgy Lebedik Date: Thu, 26 Jun 2025 18:18:54 +0300 Subject: [PATCH 09/32] Profile assisted factory, not full covered. --- .../context/profile/activity/ProfileActivity.java | 12 +++++++----- .../profile/factory/AssistedFactoryBase.java | 15 +++++++++++++++ .../profile/fragment/ProfileEventsFragment.java | 2 +- .../context/profile/fragment/ProfileFragment.java | 4 ++-- .../profile/viewmodel/ProfileEventsViewModel.java | 14 -------------- .../profile/viewmodel/ProfileViewModel.java | 14 -------------- AndroidClient/src/main/res/values-en/strings.xml | 2 +- AndroidClient/src/main/res/values/strings.xml | 2 +- 8 files changed, 27 insertions(+), 38 deletions(-) diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/ProfileActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/ProfileActivity.java index 9d9b415..5be6eed 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/ProfileActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/ProfileActivity.java @@ -191,7 +191,8 @@ private void onInit(String token, boolean isSavedInstanceStateExist) { getResources().getStringArray(R.array.nav_item_activity_titles)); setupDrawer(toolbar, icons); - drawer.getAdapter().withOnBindViewHolderListener(new OnBindViewHolderListenerImplBase()); + drawer.getAdapter() + .withOnBindViewHolderListener(new OnBindViewHolderListenerImplBase()); if (!isSavedInstanceStateExist) { lastNavItemId = DRAWER_PROFILE_ID; renderSelectedFragment(); @@ -344,7 +345,8 @@ private void renderSelectedFragment() { } // if user select the current navigation menu again, don't do anything // just close the navigation drawer - if (getSupportFragmentManager().findFragmentByTag(tag) != null) { + FragmentManager supportFM = getSupportFragmentManager(); + if (supportFM.findFragmentByTag(tag) != null) { drawer.closeDrawer(); //toggleFab(); return; @@ -372,7 +374,7 @@ private void renderSelectedFragment() { // If mPendingRunnable is not null, then add to the message queue replaceFragmentHandler.post( replaceFragment( - getSupportFragmentManager(), + supportFM, () -> createFragment(lastNavItemId), () -> tag) ); @@ -420,8 +422,8 @@ private static Runnable replaceFragment( //txn.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out); txn.replace(R.id.profile_activity_frame, fragmentP.get(), currentTagP.get()); //for some reasons txn.commit leads to errors and txn.commitAllowingStateLoss doesn't - //txn.commit(); - txn.commitAllowingStateLoss(); + txn.commit(); + //txn.commitAllowingStateLoss(); }; } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/AssistedFactoryBase.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/AssistedFactoryBase.java index 45dca10..9fb2ad7 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/AssistedFactoryBase.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/AssistedFactoryBase.java @@ -3,8 +3,23 @@ import android.content.Context; import androidx.lifecycle.ViewModel; +import androidx.lifecycle.ViewModelProvider; public interface AssistedFactoryBase { T create(String auth, Context ctx, Runnable onNotAuthenticated); + + default > ViewModelProvider.Factory factory( + F assistedFactory, + String auth, Context ctx, + Runnable onNotAuthenticated) { + return new ViewModelProvider.Factory() { + @Override + @SuppressWarnings("unchecked") + //TODO associate T2 with T? + public T2 create(Class modelClass) { + return (T2) assistedFactory.create(auth, ctx, onNotAuthenticated); + } + }; + } } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileEventsFragment.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileEventsFragment.java index 56e19f2..35ed95f 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileEventsFragment.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileEventsFragment.java @@ -87,7 +87,7 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat String auth = getAuthHeader(accountManager); viewModel = new ViewModelProvider( this, - ProfileEventsViewModel.factory( + assistedFactory.factory( assistedFactory, auth, requireContext(), () -> InfrastructureHelper.restartActivityFromFragment(this))) .get(ProfileEventsViewModel.class); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileFragment.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileFragment.java index 4561915..b3f76ea 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileFragment.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileFragment.java @@ -100,7 +100,7 @@ public void onCreate(Bundle savedInstanceState) { ((App) getActivity().getApplication()).getComponent().inject(this); - Context ctx = getContext(); + Context ctx = requireContext(); accountManager = AccountManager.get(ctx); adapter = new EventsCardAdapter( @@ -125,7 +125,7 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat String auth = getAuthHeader(accountManager); viewModel = new ViewModelProvider( this, - ProfileViewModel.factory( + assistedFactory.factory( assistedFactory, auth, requireContext(), () -> InfrastructureHelper.restartActivityFromFragment(this))) .get(ProfileViewModel.class); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileEventsViewModel.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileEventsViewModel.java index cdf1a0b..c88a93c 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileEventsViewModel.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileEventsViewModel.java @@ -7,10 +7,8 @@ import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.ViewModel; -import androidx.lifecycle.ViewModelProvider; import com.tom.meeter.context.network.dto.EventDTO; -import com.tom.meeter.context.profile.factory.ProfileEventsViewModelAssistedFactory; import com.tom.meeter.context.profile.service.ProfileService; import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; import com.tom.meeter.infrastructure.http.HttpCodes; @@ -47,18 +45,6 @@ public ProfileEventsViewModel( init(); } - public static ViewModelProvider.Factory factory( - ProfileEventsViewModelAssistedFactory assistedFactory, - String auth, Context ctx, Runnable onNotAuthenticated) { - return new ViewModelProvider.Factory() { - @Override - @SuppressWarnings("unchecked") - public T create(Class modelClass) { - return (T) assistedFactory.create(auth, ctx, onNotAuthenticated); - } - }; - } - public void init() { service.getProfileEvents(auth).enqueue( new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileViewModel.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileViewModel.java index ff11f12..d3127d2 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileViewModel.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileViewModel.java @@ -8,12 +8,10 @@ import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.ViewModel; -import androidx.lifecycle.ViewModelProvider; import com.tom.meeter.context.image.ImageDownloader; import com.tom.meeter.context.network.dto.EventDTO; import com.tom.meeter.context.network.dto.UserDTO; -import com.tom.meeter.context.profile.factory.ProfileViewModelAssistedFactory; import com.tom.meeter.context.profile.service.ProfileService; import com.tom.meeter.infrastructure.common.ImagesHelper; import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; @@ -56,18 +54,6 @@ public ProfileViewModel( init(); } - public static ViewModelProvider.Factory factory( - ProfileViewModelAssistedFactory assistedFactory, - String auth, Context ctx, Runnable onNotAuthenticated) { - return new ViewModelProvider.Factory() { - @Override - @SuppressWarnings("unchecked") - public T create(Class modelClass) { - return (T) assistedFactory.create(auth, ctx, onNotAuthenticated); - } - }; - } - public void init() { profileService.getProfile(auth).enqueue( new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { diff --git a/AndroidClient/src/main/res/values-en/strings.xml b/AndroidClient/src/main/res/values-en/strings.xml index e78aebb..2564e9c 100644 --- a/AndroidClient/src/main/res/values-en/strings.xml +++ b/AndroidClient/src/main/res/values-en/strings.xml @@ -19,7 +19,7 @@ Profile Events New event - Custom + Notifications Additional Settings Help diff --git a/AndroidClient/src/main/res/values/strings.xml b/AndroidClient/src/main/res/values/strings.xml index 8d081b2..ac3959e 100644 --- a/AndroidClient/src/main/res/values/strings.xml +++ b/AndroidClient/src/main/res/values/strings.xml @@ -18,7 +18,7 @@ Profile Events New event - Custom + Notifications Additional Settings Help From dcc58beed638fcd414c75dad764e51fa3ced5b7e Mon Sep 17 00:00:00 2001 From: Georgy Lebedik Date: Thu, 26 Jun 2025 21:23:01 +0300 Subject: [PATCH 10/32] Profile assisted factory, full covered. --- .../java/com/tom/meeter/AppComponent.java | 5 -- .../profile/activity/SubscribersActivity.java | 70 ++++------------ .../activity/SubscriptionsActivity.java | 60 ++++---------- .../profile/adapter/SubscribersAdapter.java | 39 +++++++++ ...leSubscribersViewModelAssistedFactory.java | 10 +++ ...SubscriptionsViewModelAssistedFactory.java | 10 +++ .../ProfileSubscribersViewModel.java | 83 +++++++++++-------- .../ProfileSubscriptionsViewModel.java | 50 ++++++----- .../injection/viewmodel/ViewModelFactory.java | 45 ---------- .../injection/viewmodel/ViewModelModule.java | 46 ---------- 10 files changed, 171 insertions(+), 247 deletions(-) create mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileSubscribersViewModelAssistedFactory.java create mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileSubscriptionsViewModelAssistedFactory.java delete mode 100644 AndroidClient/src/main/java/com/tom/meeter/infrastructure/injection/viewmodel/ViewModelFactory.java delete mode 100644 AndroidClient/src/main/java/com/tom/meeter/infrastructure/injection/viewmodel/ViewModelModule.java diff --git a/AndroidClient/src/main/java/com/tom/meeter/AppComponent.java b/AndroidClient/src/main/java/com/tom/meeter/AppComponent.java index 62fecc6..6658636 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/AppComponent.java +++ b/AndroidClient/src/main/java/com/tom/meeter/AppComponent.java @@ -16,8 +16,6 @@ import com.tom.meeter.context.profile.fragment.ProfileFragment; import com.tom.meeter.context.token.service.TokenService; import com.tom.meeter.context.user.service.UserService; -import com.tom.meeter.infrastructure.injection.viewmodel.ViewModelFactory; -import com.tom.meeter.infrastructure.injection.viewmodel.ViewModelModule; import javax.inject.Singleton; @@ -29,7 +27,6 @@ AppModule.class, TokenModule.class, ImageModule.class, - ViewModelModule.class, UserModule.class, EventModule.class }) @@ -44,8 +41,6 @@ public interface AppComponent { EventService provideEventService(); - ViewModelFactory viewModelFactory(); - @Component.Builder interface Builder { diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscribersActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscribersActivity.java index b5759fc..c3e8bad 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscribersActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscribersActivity.java @@ -10,29 +10,22 @@ import android.view.View; import androidx.appcompat.app.AppCompatActivity; -import androidx.lifecycle.ViewModelProviders; +import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.LinearLayoutManager; import com.tom.meeter.App; -import com.tom.meeter.context.auth.infrastructure.AuthHelper; import com.tom.meeter.context.image.ImageDownloader; import com.tom.meeter.context.profile.adapter.SubscribersAdapter; +import com.tom.meeter.context.profile.factory.ProfileSubscribersViewModelAssistedFactory; import com.tom.meeter.context.profile.service.ProfileService; -import com.tom.meeter.context.profile.subscriber.Subscriber; import com.tom.meeter.context.profile.viewmodel.ProfileSubscribersViewModel; import com.tom.meeter.context.token.service.TokenService; import com.tom.meeter.context.user.service.UserService; import com.tom.meeter.databinding.ActivityProfileSubscribersBinding; import com.tom.meeter.infrastructure.components.binder.PhotoDownloaderWithCacheSubscriberBinder; -import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; -import com.tom.meeter.infrastructure.http.HttpCodes; -import com.tom.meeter.infrastructure.injection.viewmodel.ViewModelFactory; import javax.inject.Inject; -import retrofit2.Call; -import retrofit2.Response; - public class SubscribersActivity extends AppCompatActivity { private static final String TAG = SubscribersActivity.class.getCanonicalName(); @@ -41,21 +34,17 @@ public class SubscribersActivity extends AppCompatActivity { ProfileService profileService; @Inject TokenService tokenService; - - ActivityProfileSubscribersBinding binding; - - private AccountManager accountManager; - @Inject - ViewModelFactory viewModelFactory; + ProfileSubscribersViewModelAssistedFactory assistedFactory; @Inject ImageDownloader imgDownloader; @Inject UserService userService; + private AccountManager accountManager; + private ActivityProfileSubscribersBinding binding; private SubscribersAdapter adapter; - - private ProfileSubscribersViewModel profileSubscribersViewModel; + private ProfileSubscribersViewModel viewModel; @Override protected void onCreate(Bundle savedInstanceState) { @@ -78,51 +67,28 @@ private void onInit(String token) { View view = binding.getRoot(); setContentView(view); + String auth = getAuthHeader(accountManager); adapter = new SubscribersAdapter( new PhotoDownloaderWithCacheSubscriberBinder( this, imgDownloader, (user) -> dispatchToUserActivity(this, user.getId()), - this::onSubUnsubClick, + (sub, pos) -> adapter.onSubUnsubClick( + userService, sub, pos, this::recreate, this, auth), this::recreate )); - profileSubscribersViewModel = ViewModelProviders.of(this, viewModelFactory) - .get(ProfileSubscribersViewModel.class); - profileSubscribersViewModel.fetchProfileSubscribers(getAuthHeader(accountManager), this); - - profileSubscribersViewModel.getSubscribersLiveData() - .observe(this, subs -> adapter.setData(subs)); binding.recyclerSubscribers.setLayoutManager(new LinearLayoutManager(this)); binding.recyclerSubscribers.setAdapter(adapter); - } - private void onSubUnsubClick(Subscriber sub, int position) { - if (sub.isAmISubscribedTo()) { - userService.unsubscribe(AuthHelper.getAuthHeader(accountManager), sub.getUser().getId()) - .enqueue(new BaseOnNotAuthenticatedCallback<>(this, this::recreate) { - @Override - public void onResponse(Call call, Response resp) { - super.onResponse(call, resp); - if (resp.code() == HttpCodes.OK) { - sub.setAmISubscribedTo(false); - adapter.notifyItemChanged(position); - } - } - }); - } else { - userService.subscribe(AuthHelper.getAuthHeader(accountManager), sub.getUser().getId()) - .enqueue(new BaseOnNotAuthenticatedCallback<>(this, this::recreate) { - @Override - public void onResponse(Call call, Response resp) { - super.onResponse(call, resp); - if (resp.code() == HttpCodes.OK) { - sub.setAmISubscribedTo(true); - adapter.notifyItemChanged(position); - } - } - }); - } - return; + viewModel = new ViewModelProvider( + this, + assistedFactory.factory( + assistedFactory, auth, this, + this::recreate)) + .get(ProfileSubscribersViewModel.class); + + viewModel.getSubscribers() + .observe(this, subs -> adapter.setData(subs)); } @Override diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscriptionsActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscriptionsActivity.java index e8e532f..3efd74a 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscriptionsActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscriptionsActivity.java @@ -10,27 +10,21 @@ import android.view.View; import androidx.appcompat.app.AppCompatActivity; -import androidx.lifecycle.ViewModelProviders; +import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.LinearLayoutManager; import com.tom.meeter.App; -import com.tom.meeter.context.auth.infrastructure.AuthHelper; import com.tom.meeter.context.image.ImageDownloader; import com.tom.meeter.context.profile.adapter.SubscribersAdapter; -import com.tom.meeter.context.profile.subscriber.Subscriber; +import com.tom.meeter.context.profile.factory.ProfileSubscriptionsViewModelAssistedFactory; import com.tom.meeter.context.profile.viewmodel.ProfileSubscriptionsViewModel; import com.tom.meeter.context.token.service.TokenService; import com.tom.meeter.context.user.service.UserService; import com.tom.meeter.databinding.ActivityProfileSubscriptionsBinding; import com.tom.meeter.infrastructure.components.binder.PhotoDownloaderWithCacheSubscriberBinder; -import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; -import com.tom.meeter.infrastructure.injection.viewmodel.ViewModelFactory; import javax.inject.Inject; -import retrofit2.Call; -import retrofit2.Response; - public class SubscriptionsActivity extends AppCompatActivity { private static final String TAG = SubscribersActivity.class.getCanonicalName(); @@ -38,19 +32,16 @@ public class SubscriptionsActivity extends AppCompatActivity { @Inject TokenService tokenService; @Inject - ViewModelFactory viewModelFactory; + ProfileSubscriptionsViewModelAssistedFactory assistedFactory; @Inject ImageDownloader imgDownloader; @Inject UserService userService; private ActivityProfileSubscriptionsBinding binding; - private AccountManager accountManager; - private SubscribersAdapter adapter; - - private ProfileSubscriptionsViewModel profileSubscriptionsViewModel; + private ProfileSubscriptionsViewModel viewModel; @Override protected void onCreate(Bundle savedInstanceState) { @@ -73,47 +64,28 @@ private void onInit(String token) { View view = binding.getRoot(); setContentView(view); + String auth = getAuthHeader(accountManager); adapter = new SubscribersAdapter( new PhotoDownloaderWithCacheSubscriberBinder( this, imgDownloader, (e) -> dispatchToUserActivity(this, e.getId()), - this::onSubUnsubClick, + (sub, pos) -> adapter.onSubUnsubClick( + userService, sub, pos, this::recreate, this, auth), this::recreate )); - profileSubscriptionsViewModel = ViewModelProviders.of(this, viewModelFactory) - .get(ProfileSubscriptionsViewModel.class); - profileSubscriptionsViewModel.fetchProfileSubscriptions(getAuthHeader(accountManager), this); - - profileSubscriptionsViewModel.getSubscriptionsLiveData() - .observe(this, subs -> adapter.setData(subs)); binding.recyclerSubscriptions.setLayoutManager(new LinearLayoutManager(this)); binding.recyclerSubscriptions.setAdapter(adapter); - } - private void onSubUnsubClick(Subscriber sub, int position) { - if (sub.isAmISubscribedTo()) { - userService.unsubscribe(AuthHelper.getAuthHeader(accountManager), sub.getUser().getId()) - .enqueue(new BaseOnNotAuthenticatedCallback<>(this, this::recreate) { - @Override - public void onResponse(Call call, Response response) { - super.onResponse(call, response); - sub.setAmISubscribedTo(false); - adapter.notifyItemChanged(position); - } - }); - } else { - userService.subscribe(AuthHelper.getAuthHeader(accountManager), sub.getUser().getId()) - .enqueue(new BaseOnNotAuthenticatedCallback<>(this, this::recreate) { - @Override - public void onResponse(Call call, Response response) { - super.onResponse(call, response); - sub.setAmISubscribedTo(true); - adapter.notifyItemChanged(position); - } - }); - } - return; + viewModel = new ViewModelProvider( + this, + assistedFactory.factory( + assistedFactory, auth, this, + this::recreate)) + .get(ProfileSubscriptionsViewModel.class); + + viewModel.getSubscriptions() + .observe(this, subs -> adapter.setData(subs)); } @Override diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/adapter/SubscribersAdapter.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/adapter/SubscribersAdapter.java index 7f2fc23..fb4ef17 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/adapter/SubscribersAdapter.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/adapter/SubscribersAdapter.java @@ -2,15 +2,23 @@ import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; +import android.content.Context; import android.view.LayoutInflater; import android.view.ViewGroup; import androidx.recyclerview.widget.RecyclerView; +import com.tom.meeter.context.profile.subscriber.Subscriber; +import com.tom.meeter.context.user.service.UserService; import com.tom.meeter.databinding.ActivityProfileSubscriberItemBinding; import com.tom.meeter.infrastructure.components.adapter.BaseSubscriberAdapter; import com.tom.meeter.infrastructure.components.binder.SubscriberBinder; import com.tom.meeter.infrastructure.components.viewholder.SubscriberViewHolder; +import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; +import com.tom.meeter.infrastructure.http.HttpCodes; + +import retrofit2.Call; +import retrofit2.Response; public class SubscribersAdapter extends BaseSubscriberAdapter { @@ -34,4 +42,35 @@ public void onAttachedToRecyclerView(RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); logMethod(TAG, this); } + + public void onSubUnsubClick( + UserService service, Subscriber sub, int position, + Runnable onAuthFail, Context ctx, String auth) { + if (sub.isAmISubscribedTo()) { + service.unsubscribe(auth, sub.getUser().getId()) + .enqueue(new BaseOnNotAuthenticatedCallback<>(ctx, onAuthFail) { + @Override + public void onResponse(Call call, Response resp) { + super.onResponse(call, resp); + if (resp.code() == HttpCodes.OK) { + sub.setAmISubscribedTo(false); + SubscribersAdapter.this.notifyItemChanged(position); + } + } + }); + } else { + service.subscribe(auth, sub.getUser().getId()) + .enqueue(new BaseOnNotAuthenticatedCallback<>(ctx, onAuthFail) { + @Override + public void onResponse(Call call, Response resp) { + super.onResponse(call, resp); + if (resp.code() == HttpCodes.OK) { + sub.setAmISubscribedTo(true); + SubscribersAdapter.this.notifyItemChanged(position); + } + } + }); + } + return; + } } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileSubscribersViewModelAssistedFactory.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileSubscribersViewModelAssistedFactory.java new file mode 100644 index 0000000..7ce1963 --- /dev/null +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileSubscribersViewModelAssistedFactory.java @@ -0,0 +1,10 @@ +package com.tom.meeter.context.profile.factory; + +import com.tom.meeter.context.profile.viewmodel.ProfileSubscribersViewModel; + +import dagger.assisted.AssistedFactory; + +@AssistedFactory +public interface ProfileSubscribersViewModelAssistedFactory + extends AssistedFactoryBase { +} diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileSubscriptionsViewModelAssistedFactory.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileSubscriptionsViewModelAssistedFactory.java new file mode 100644 index 0000000..c399b82 --- /dev/null +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileSubscriptionsViewModelAssistedFactory.java @@ -0,0 +1,10 @@ +package com.tom.meeter.context.profile.factory; + +import com.tom.meeter.context.profile.viewmodel.ProfileSubscriptionsViewModel; + +import dagger.assisted.AssistedFactory; + +@AssistedFactory +public interface ProfileSubscriptionsViewModelAssistedFactory + extends AssistedFactoryBase { +} diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileSubscribersViewModel.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileSubscribersViewModel.java index 66cf711..016938b 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileSubscribersViewModel.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileSubscribersViewModel.java @@ -2,7 +2,7 @@ import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; -import android.app.Activity; +import android.content.Context; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; @@ -19,8 +19,8 @@ import java.util.Map; import java.util.stream.Collectors; -import javax.inject.Inject; - +import dagger.assisted.Assisted; +import dagger.assisted.AssistedInject; import retrofit2.Call; import retrofit2.Response; @@ -28,61 +28,72 @@ public class ProfileSubscribersViewModel extends ViewModel { private static final String TAG = ProfileSubscribersViewModel.class.getCanonicalName(); - private final MutableLiveData> subscribersLiveData = new MutableLiveData<>(); + private final ProfileService service; + private final String auth; + private final Context ctx; + private final Runnable onNotAuthenticated; - private final ProfileService profileService; + private final MutableLiveData> subscribers = new MutableLiveData<>(); - @Inject - public ProfileSubscribersViewModel(ProfileService profileService) { + @AssistedInject + public ProfileSubscribersViewModel( + ProfileService service, + @Assisted String auth, + @Assisted Context ctx, + @Assisted Runnable onNotAuthenticated) { logMethod(TAG, this); - this.profileService = profileService; + this.service = service; + this.auth = auth; + this.ctx = ctx.getApplicationContext(); + this.onNotAuthenticated = onNotAuthenticated; + init(); } - public void fetchProfileSubscribers(String auth, Activity activity) { - profileService.getMySubscriptions(auth).enqueue( - new BaseOnNotAuthenticatedCallback<>(activity, activity::recreate) { + public void init() { + service.getMySubscriptions(auth).enqueue( + new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { @Override - public void onResponse(Call> call, Response> resp) { + public void onResponse( + Call> call, Response> resp) { super.onResponse(call, resp); - if (resp.code() == HttpCodes.OK) { - getSubscribers( - auth, - activity, - resp.body() - .stream() - .collect(Collectors.toMap( - UserDTO::getId, item -> item))); + if (resp.code() != HttpCodes.OK || resp.body() == null) { return; } + initSubscribers( + resp.body() + .stream() + .collect(Collectors.toMap(UserDTO::getId, item -> item))); + return; } } ); } - private void getSubscribers( - String auth, Activity activity, Map mySubscriptions) { - profileService.getMySubscribers(auth).enqueue( - new BaseOnNotAuthenticatedCallback<>(activity, activity::recreate) { + private void initSubscribers(Map mySubscriptions) { + service.getMySubscribers(auth).enqueue( + new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { @Override - public void onResponse(Call> call, Response> resp) { + public void onResponse( + Call> call, Response> resp) { super.onResponse(call, resp); - if (resp.code() == HttpCodes.OK) { - List subscribers = new ArrayList<>(); - for (UserDTO subscriber : resp.body()) { - subscribers.add( - new Subscriber( - subscriber, - mySubscriptions.get(subscriber.getId()) != null)); - } - subscribersLiveData.setValue(subscribers); + if (resp.code() != HttpCodes.OK || resp.body() == null) { return; } + List result = new ArrayList<>(); + for (UserDTO subscriber : resp.body()) { + result.add( + new Subscriber( + subscriber, + mySubscriptions.get(subscriber.getId()) != null)); + } + ProfileSubscribersViewModel.this.subscribers.setValue(result); + return; } } ); } - public LiveData> getSubscribersLiveData() { - return subscribersLiveData; + public LiveData> getSubscribers() { + return subscribers; } } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileSubscriptionsViewModel.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileSubscriptionsViewModel.java index 9adf60c..957184a 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileSubscriptionsViewModel.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileSubscriptionsViewModel.java @@ -2,7 +2,7 @@ import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; -import android.app.Activity; +import android.content.Context; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; @@ -17,8 +17,8 @@ import java.util.ArrayList; import java.util.List; -import javax.inject.Inject; - +import dagger.assisted.Assisted; +import dagger.assisted.AssistedInject; import retrofit2.Call; import retrofit2.Response; @@ -26,36 +26,48 @@ public class ProfileSubscriptionsViewModel extends ViewModel { private static final String TAG = ProfileSubscribersViewModel.class.getCanonicalName(); - private final MutableLiveData> subscriptionsLiveData = new MutableLiveData<>(); + private final ProfileService service; + private final String auth; + private final Context ctx; + private final Runnable onNotAuthenticated; - private final ProfileService profileService; + private final MutableLiveData> subscriptions = new MutableLiveData<>(); - @Inject - public ProfileSubscriptionsViewModel(ProfileService profileService) { + @AssistedInject + public ProfileSubscriptionsViewModel( + ProfileService service, + @Assisted String auth, + @Assisted Context ctx, + @Assisted Runnable onNotAuthenticated) { logMethod(TAG, this); - this.profileService = profileService; + this.service = service; + this.auth = auth; + this.ctx = ctx.getApplicationContext(); + this.onNotAuthenticated = onNotAuthenticated; + init(); } - public void fetchProfileSubscriptions(String auth, Activity activity) { - profileService.getMySubscriptions(auth).enqueue( - new BaseOnNotAuthenticatedCallback<>(activity, activity::recreate) { + public void init() { + service.getMySubscriptions(auth).enqueue( + new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { @Override public void onResponse(Call> call, Response> resp) { super.onResponse(call, resp); - if (resp.code() == HttpCodes.OK) { - List subscribers = new ArrayList<>(); - for (UserDTO subscription : resp.body()) { - subscribers.add(new Subscriber(subscription, true)); - } - subscriptionsLiveData.setValue(subscribers); + if (resp.code() != HttpCodes.OK || resp.body() == null) { return; } + List result = new ArrayList<>(); + for (UserDTO subscription : resp.body()) { + result.add(new Subscriber(subscription, true)); + } + subscriptions.setValue(result); + return; } } ); } - public LiveData> getSubscriptionsLiveData() { - return subscriptionsLiveData; + public LiveData> getSubscriptions() { + return subscriptions; } } diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/injection/viewmodel/ViewModelFactory.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/injection/viewmodel/ViewModelFactory.java deleted file mode 100644 index d884280..0000000 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/injection/viewmodel/ViewModelFactory.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.tom.meeter.infrastructure.injection.viewmodel; - -import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; - -import android.util.Log; - -import androidx.lifecycle.ViewModel; -import androidx.lifecycle.ViewModelProvider; - -import java.util.Map; - -import javax.inject.Inject; -import javax.inject.Provider; -import javax.inject.Singleton; - -@Singleton -public class ViewModelFactory implements ViewModelProvider.Factory { - - private static final String TAG = ViewModelFactory.class.getCanonicalName(); - private final Map, Provider> viewModels; - - @Inject - public ViewModelFactory(Map, Provider> viewModels) { - logMethod(TAG, this); - this.viewModels = viewModels; - } - - @Override - public T create(Class modelClass) { - Log.d(TAG, "ViewModelFactory creates " + modelClass); - - Provider viewModelProvider = viewModels.get(modelClass); - - if (viewModelProvider == null) { - throw new IllegalArgumentException("ViewModel class " + modelClass - + " not found. Check " + ViewModelModule.class.getCanonicalName() - + " file to be properly aligned."); - } - Log.d(TAG, "Before viewModelProvider.get() " + modelClass); - T t = (T) viewModelProvider.get(); - Log.d(TAG, "After viewModelProvider.get()" + modelClass); - - return t; - } -} diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/injection/viewmodel/ViewModelModule.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/injection/viewmodel/ViewModelModule.java deleted file mode 100644 index 757f4f3..0000000 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/injection/viewmodel/ViewModelModule.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.tom.meeter.infrastructure.injection.viewmodel; - -import android.util.Log; - -import androidx.lifecycle.ViewModel; - -import com.tom.meeter.context.profile.viewmodel.ProfileEventsViewModel; -import com.tom.meeter.context.profile.viewmodel.ProfileSubscribersViewModel; -import com.tom.meeter.context.profile.viewmodel.ProfileSubscriptionsViewModel; -import com.tom.meeter.context.profile.viewmodel.ProfileViewModel; - -import dagger.Binds; -import dagger.Module; -import dagger.multibindings.IntoMap; - -@Module -public abstract class ViewModelModule { - - private static final String TAG = ViewModelModule.class.getCanonicalName(); - - public ViewModelModule() { - Log.d(TAG, "Configuring ViewModelModule..."); - } - -/* @Binds - @IntoMap - @ViewModelKey(ProfileViewModel.class) - abstract ViewModel profileViewModel(ProfileViewModel profileViewModel);*/ - -/* - @Binds - @IntoMap - @ViewModelKey(ProfileEventsViewModel.class) - abstract ViewModel profileEventsViewModel(ProfileEventsViewModel profileEventsViewModel); -*/ - - @Binds - @IntoMap - @ViewModelKey(ProfileSubscribersViewModel.class) - abstract ViewModel profileSubscribersViewModel(ProfileSubscribersViewModel psvm); - - @Binds - @IntoMap - @ViewModelKey(ProfileSubscriptionsViewModel.class) - abstract ViewModel profileSubscriptionsViewModel(ProfileSubscriptionsViewModel psvm); -} From 62d8f9d7c3ce85784f1fb5b806332f188955806b Mon Sep 17 00:00:00 2001 From: Georgy Lebedik Date: Thu, 26 Jun 2025 22:16:48 +0300 Subject: [PATCH 11/32] Assisted factory for user module --- .../meeter/context/image/ImageDownloader.java | 19 --- .../meeter/context/user/UserComponent.java | 1 - .../context/user/UserViewModelModule.java | 30 ----- .../context/user/activity/UserActivity.java | 31 ++--- .../activity/UserSubscribersActivity.java | 24 ++-- .../activity/UserSubscriptionsActivity.java | 22 ++-- .../user/factory/AssistedFactoryBase.java | 27 +++++ ...erSubscribersViewModelAssistedFactory.java | 20 ++++ ...SubscriptionsViewModelAssistedFactory.java | 20 ++++ .../factory/UserViewModelAssistedFactory.java | 20 ++++ .../user/factory/UserViewModelFactory.java | 47 -------- .../viewmodel/UserSubscribersViewModel.java | 47 +++++--- .../viewmodel/UserSubscriptionsViewModel.java | 47 +++++--- .../context/user/viewmodel/UserViewModel.java | 111 +++++++++++------- ...toDownloaderWithCacheSubscriberBinder.java | 8 +- .../PhotoDownloaderWithCacheUserBinder.java | 9 +- .../injection/viewmodel/ViewModelKey.java | 17 --- 17 files changed, 270 insertions(+), 230 deletions(-) delete mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/user/UserViewModelModule.java create mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/user/factory/AssistedFactoryBase.java create mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscribersViewModelAssistedFactory.java create mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscriptionsViewModelAssistedFactory.java create mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserViewModelAssistedFactory.java delete mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserViewModelFactory.java delete mode 100644 AndroidClient/src/main/java/com/tom/meeter/infrastructure/injection/viewmodel/ViewModelKey.java diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/image/ImageDownloader.java b/AndroidClient/src/main/java/com/tom/meeter/context/image/ImageDownloader.java index 19865e6..7173553 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/image/ImageDownloader.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/image/ImageDownloader.java @@ -73,25 +73,6 @@ public void onResponse(Call call, Response response) }); } - @Deprecated - public void downloadUserImage( - String photoPath, Context ctx, - Consumer onDownloaded, Runnable onNotAuthenticated) { - imageService.downloadUserImage(getAuthHeader(AccountManager.get(ctx)), photoPath) - .enqueue(new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { - @Override - public void onResponse(Call call, Response response) { - super.onResponse(call, response); - if (response.code() == HttpCodes.OK) { - try (ResponseBody body = response.body()) { - onDownloaded.accept(body); - return; - } - } - } - }); - } - public void downloadUserImage( String photoPath, Context ctx, Function converter, diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/UserComponent.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/UserComponent.java index 754430e..0c402f4 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/UserComponent.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/UserComponent.java @@ -12,7 +12,6 @@ @UserScope @Component( - modules = {UserViewModelModule.class}, dependencies = {AppComponent.class}) public interface UserComponent { diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/UserViewModelModule.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/UserViewModelModule.java deleted file mode 100644 index 6bd8210..0000000 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/UserViewModelModule.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.tom.meeter.context.user; - -import androidx.lifecycle.ViewModel; - -import com.tom.meeter.context.user.viewmodel.UserSubscribersViewModel; -import com.tom.meeter.context.user.viewmodel.UserSubscriptionsViewModel; -import com.tom.meeter.context.user.viewmodel.UserViewModel; -import com.tom.meeter.infrastructure.injection.viewmodel.ViewModelKey; - -import dagger.Binds; -import dagger.Module; -import dagger.multibindings.IntoMap; - -@Module -public abstract class UserViewModelModule { - @Binds - @IntoMap - @ViewModelKey(UserViewModel.class) - abstract ViewModel userViewModel(UserViewModel userViewModel); - - @Binds - @IntoMap - @ViewModelKey(UserSubscribersViewModel.class) - abstract ViewModel userSubscribersViewModel(UserSubscribersViewModel usvm); - - @Binds - @IntoMap - @ViewModelKey(UserSubscriptionsViewModel.class) - abstract ViewModel userSubscriptionsViewModel(UserSubscriptionsViewModel usvm); -} diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java index 979e72d..9796072 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java @@ -7,7 +7,6 @@ import static com.tom.meeter.infrastructure.common.CommonHelper.EMPTY_STR; import static com.tom.meeter.infrastructure.common.CommonHelper.genderResolver; import static com.tom.meeter.infrastructure.common.DateHelper.getAgeFromDate; -import static com.tom.meeter.infrastructure.common.ImagesHelper.bigCircleImage; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.showMessage; @@ -31,7 +30,7 @@ import com.tom.meeter.context.image.ImageDownloader; import com.tom.meeter.context.profile.activity.ProfileActivity; import com.tom.meeter.context.token.service.TokenService; -import com.tom.meeter.context.user.factory.UserViewModelFactory; +import com.tom.meeter.context.user.factory.UserViewModelAssistedFactory; import com.tom.meeter.context.user.service.UserService; import com.tom.meeter.context.user.viewmodel.UserViewModel; import com.tom.meeter.databinding.ActivityUserBinding; @@ -58,12 +57,12 @@ public class UserActivity extends AppCompatActivity { @Inject UserService userService; @Inject - UserViewModelFactory viewModelFactory; + UserViewModelAssistedFactory assistedFactory; @Inject ImageDownloader imgDownloader; private ActivityUserBinding binding; - private UserViewModel userViewModel; + private UserViewModel viewModel; private String userId; private AccountManager accountManager; private EventsCardAdapter adapter; @@ -151,10 +150,17 @@ public void onResponse(Call call, Response resp) { } }); - userViewModel = new ViewModelProvider(this, viewModelFactory) + viewModel = new ViewModelProvider( + this, + assistedFactory.factory( + assistedFactory, Globals.getAuthHeader(token), + userId, this, this::recreate)) .get(UserViewModel.class); - userViewModel.fetchUserInformation(Globals.getAuthHeader(token), userId, this); - userViewModel.getUserLiveData() + + binding.events.setLayoutManager(new GridLayoutManager(this, 2)); + binding.events.setAdapter(adapter); + + viewModel.getUser() .observe(this, user -> { binding.name.setText(user.getName()); binding.gender.setText(genderResolver(getApplicationContext(), user.getGender())); @@ -165,17 +171,14 @@ public void onResponse(Call call, Response resp) { binding.age.setText(getString(R.string.profile_age_format, getAgeFromDate(birthday))); binding.info.setText(user.getInfo()); }); - userViewModel.getAmISubscriber() + viewModel.getAmISubscriber() .observe(this, this::updateAmISubscriber); - userViewModel.getUserEventsLiveData() + viewModel.getEvents() .observe(this, events -> adapter.setData(events)); - userViewModel.getUserPhotoLiveData() + viewModel.getPhoto() .observe( this, - photo -> binding.photo.setImageBitmap(bigCircleImage(photo))); - - binding.events.setLayoutManager(new GridLayoutManager(this, 2)); - binding.events.setAdapter(adapter); + photo -> binding.photo.setImageBitmap(photo)); binding.subscribers.setOnClickListener( v -> dispatchToUserSubscribersActivity(this, userId)); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscribersActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscribersActivity.java index 980da37..9349426 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscribersActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscribersActivity.java @@ -1,7 +1,6 @@ package com.tom.meeter.context.user.activity; import static com.tom.meeter.context.auth.infrastructure.AuthHelper.checkToken; -import static com.tom.meeter.context.auth.infrastructure.AuthHelper.getAuthHeader; import static com.tom.meeter.context.user.activity.UserActivity.dispatchToUserActivity; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; @@ -16,16 +15,17 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; -import androidx.lifecycle.ViewModelProviders; +import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.LinearLayoutManager; import com.tom.meeter.App; import com.tom.meeter.context.image.ImageDownloader; import com.tom.meeter.context.token.service.TokenService; import com.tom.meeter.context.user.adapter.UsersAdapter; +import com.tom.meeter.context.user.factory.UserSubscribersViewModelAssistedFactory; import com.tom.meeter.context.user.viewmodel.UserSubscribersViewModel; -import com.tom.meeter.context.user.factory.UserViewModelFactory; import com.tom.meeter.databinding.ActivityProfileSubscribersBinding; +import com.tom.meeter.infrastructure.common.Globals; import com.tom.meeter.infrastructure.components.binder.PhotoDownloaderWithCacheUserBinder; import javax.inject.Inject; @@ -37,13 +37,13 @@ public class UserSubscribersActivity extends AppCompatActivity { @Inject TokenService tokenService; @Inject - UserViewModelFactory viewModelFactory; + UserSubscribersViewModelAssistedFactory assistedFactory; @Inject ImageDownloader imgDownloader; private AccountManager accountManager; private ActivityProfileSubscribersBinding binding; - private UserSubscribersViewModel userSubscribersViewModel; + private UserSubscribersViewModel viewModel; private UsersAdapter adapter; private String userId; @@ -85,14 +85,18 @@ private void onInit(String token) { View view = binding.getRoot(); setContentView(view); - userSubscribersViewModel = ViewModelProviders.of(this, viewModelFactory) + binding.recyclerSubscribers.setLayoutManager(new LinearLayoutManager(this)); + binding.recyclerSubscribers.setAdapter(adapter); + + viewModel = new ViewModelProvider( + this, + assistedFactory.factory( + assistedFactory, Globals.getAuthHeader(token), + userId, this, this::recreate)) .get(UserSubscribersViewModel.class); - userSubscribersViewModel.fetchUserSubscribers(getAuthHeader(accountManager), userId, this); - userSubscribersViewModel.getSubscribersLiveData() + viewModel.getSubscribers() .observe(this, subs -> adapter.setData(subs)); - binding.recyclerSubscribers.setLayoutManager(new LinearLayoutManager(this)); - binding.recyclerSubscribers.setAdapter(adapter); } @Nullable diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscriptionsActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscriptionsActivity.java index 6bd1ee2..45fe749 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscriptionsActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscriptionsActivity.java @@ -1,7 +1,6 @@ package com.tom.meeter.context.user.activity; import static com.tom.meeter.context.auth.infrastructure.AuthHelper.checkToken; -import static com.tom.meeter.context.auth.infrastructure.AuthHelper.getAuthHeader; import static com.tom.meeter.context.user.activity.UserActivity.dispatchToUserActivity; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; @@ -16,16 +15,17 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; -import androidx.lifecycle.ViewModelProviders; +import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.LinearLayoutManager; import com.tom.meeter.App; import com.tom.meeter.context.image.ImageDownloader; import com.tom.meeter.context.token.service.TokenService; import com.tom.meeter.context.user.adapter.UsersAdapter; +import com.tom.meeter.context.user.factory.UserViewModelAssistedFactory; import com.tom.meeter.context.user.viewmodel.UserSubscriptionsViewModel; -import com.tom.meeter.context.user.factory.UserViewModelFactory; import com.tom.meeter.databinding.ActivityProfileSubscriptionsBinding; +import com.tom.meeter.infrastructure.common.Globals; import com.tom.meeter.infrastructure.components.binder.PhotoDownloaderWithCacheUserBinder; import javax.inject.Inject; @@ -37,12 +37,12 @@ public class UserSubscriptionsActivity extends AppCompatActivity { @Inject TokenService tokenService; @Inject - UserViewModelFactory viewModelFactory; + UserViewModelAssistedFactory assistedFactory; @Inject ImageDownloader imgDownloader; private ActivityProfileSubscriptionsBinding binding; - private UserSubscriptionsViewModel userSubscriptionsViewModel; + private UserSubscriptionsViewModel viewModel; private UsersAdapter adapter; private AccountManager accountManager; private String userId; @@ -85,14 +85,18 @@ private void onInit(String token) { View view = binding.getRoot(); setContentView(view); - userSubscriptionsViewModel = ViewModelProviders.of(this, viewModelFactory) + viewModel = new ViewModelProvider( + this, + assistedFactory.factory( + assistedFactory, Globals.getAuthHeader(token), userId, + this, this::recreate)) .get(UserSubscriptionsViewModel.class); - userSubscriptionsViewModel.fetchUserSubscriptions(getAuthHeader(accountManager), userId, this); - userSubscriptionsViewModel.getSubscriptionsLiveData() - .observe(this, subs -> adapter.setData(subs)); binding.recyclerSubscriptions.setLayoutManager(new LinearLayoutManager(this)); binding.recyclerSubscriptions.setAdapter(adapter); + + viewModel.getSubscriptions() + .observe(this, subs -> adapter.setData(subs)); } @Nullable diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/AssistedFactoryBase.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/AssistedFactoryBase.java new file mode 100644 index 0000000..c1bd4f1 --- /dev/null +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/AssistedFactoryBase.java @@ -0,0 +1,27 @@ +package com.tom.meeter.context.user.factory; + +import android.content.Context; + +import androidx.lifecycle.ViewModel; +import androidx.lifecycle.ViewModelProvider; + +public interface AssistedFactoryBase { + + String ASSISTED_AUTH = "assisted_auth"; + String ASSISTED_USER_ID = "assisted_user_id"; + + T create(String auth, String userId, Context ctx, Runnable onNotAuthenticated); + + default > ViewModelProvider.Factory factory( + F assistedFactory,String auth, String userId, Context ctx, + Runnable onNotAuthenticated) { + return new ViewModelProvider.Factory() { + @Override + @SuppressWarnings("unchecked") + //TODO associate T2 with T? + public T2 create(Class modelClass) { + return (T2) assistedFactory.create(auth, userId, ctx, onNotAuthenticated); + } + }; + } +} diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscribersViewModelAssistedFactory.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscribersViewModelAssistedFactory.java new file mode 100644 index 0000000..23770ba --- /dev/null +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscribersViewModelAssistedFactory.java @@ -0,0 +1,20 @@ +package com.tom.meeter.context.user.factory; + +import android.content.Context; + +import com.tom.meeter.context.user.viewmodel.UserSubscribersViewModel; + +import dagger.assisted.Assisted; +import dagger.assisted.AssistedFactory; + +@AssistedFactory +public interface UserSubscribersViewModelAssistedFactory + extends AssistedFactoryBase { + + @Override + UserSubscribersViewModel create( + @Assisted(ASSISTED_AUTH) String auth, + @Assisted(ASSISTED_USER_ID) String userId, + Context ctx, + Runnable onNotAuthenticated); +} diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscriptionsViewModelAssistedFactory.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscriptionsViewModelAssistedFactory.java new file mode 100644 index 0000000..2e04968 --- /dev/null +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscriptionsViewModelAssistedFactory.java @@ -0,0 +1,20 @@ +package com.tom.meeter.context.user.factory; + +import android.content.Context; + +import com.tom.meeter.context.user.viewmodel.UserSubscriptionsViewModel; + +import dagger.assisted.Assisted; +import dagger.assisted.AssistedFactory; + +@AssistedFactory +public interface UserSubscriptionsViewModelAssistedFactory + extends AssistedFactoryBase { + + @Override + UserSubscriptionsViewModel create( + @Assisted(ASSISTED_AUTH) String auth, + @Assisted(ASSISTED_USER_ID) String userId, + Context ctx, + Runnable onNotAuthenticated); +} diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserViewModelAssistedFactory.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserViewModelAssistedFactory.java new file mode 100644 index 0000000..0527ced --- /dev/null +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserViewModelAssistedFactory.java @@ -0,0 +1,20 @@ +package com.tom.meeter.context.user.factory; + +import android.content.Context; + +import com.tom.meeter.context.user.viewmodel.UserViewModel; + +import dagger.assisted.Assisted; +import dagger.assisted.AssistedFactory; + +@AssistedFactory +public interface UserViewModelAssistedFactory + extends AssistedFactoryBase { + + @Override + UserViewModel create( + @Assisted(ASSISTED_AUTH) String auth, + @Assisted(ASSISTED_USER_ID) String userId, + Context ctx, + Runnable onNotAuthenticated); +} diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserViewModelFactory.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserViewModelFactory.java deleted file mode 100644 index 8b29e9b..0000000 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserViewModelFactory.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.tom.meeter.context.user.factory; - -import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; - -import android.util.Log; - -import androidx.lifecycle.ViewModel; -import androidx.lifecycle.ViewModelProvider; - -import com.tom.meeter.context.user.UserScope; -import com.tom.meeter.context.user.UserViewModelModule; - -import java.util.Map; - -import javax.inject.Inject; -import javax.inject.Provider; - -@UserScope -public class UserViewModelFactory implements ViewModelProvider.Factory { - - private static final String TAG = UserViewModelFactory.class.getCanonicalName(); - private final Map, Provider> viewModels; - - @Inject - public UserViewModelFactory(Map, Provider> viewModels) { - logMethod(TAG, this); - this.viewModels = viewModels; - } - - @Override - public T create(Class modelClass) { - Log.d(TAG, "UserViewModelFactory creates " + modelClass); - - Provider viewModelProvider = viewModels.get(modelClass); - - if (viewModelProvider == null) { - throw new IllegalArgumentException("ViewModel class " + modelClass - + " not found. Check " + UserViewModelModule.class.getCanonicalName() - + " file to be properly aligned."); - } - Log.d(TAG, "Before viewModelProvider.get() " + modelClass); - T t = (T) viewModelProvider.get(); - Log.d(TAG, "After viewModelProvider.get()" + modelClass); - - return t; - } -} diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserSubscribersViewModel.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserSubscribersViewModel.java index b585400..848cde5 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserSubscribersViewModel.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserSubscribersViewModel.java @@ -1,8 +1,10 @@ package com.tom.meeter.context.user.viewmodel; +import static com.tom.meeter.context.user.factory.AssistedFactoryBase.ASSISTED_AUTH; +import static com.tom.meeter.context.user.factory.AssistedFactoryBase.ASSISTED_USER_ID; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; -import android.app.Activity; +import android.content.Context; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; @@ -15,8 +17,8 @@ import java.util.List; -import javax.inject.Inject; - +import dagger.assisted.Assisted; +import dagger.assisted.AssistedInject; import retrofit2.Call; import retrofit2.Response; @@ -24,32 +26,47 @@ public class UserSubscribersViewModel extends ViewModel { private static final String TAG = UserSubscribersViewModel.class.getCanonicalName(); - private final MutableLiveData> subscribersLiveData = new MutableLiveData<>(); + private final UserService service; + private final String auth; + private final String userId; + private final Context ctx; + private final Runnable onNotAuthenticated; - private final UserService userService; + private final MutableLiveData> subscribers = new MutableLiveData<>(); - @Inject - public UserSubscribersViewModel(UserService userService) { + @AssistedInject + public UserSubscribersViewModel( + UserService service, + @Assisted(ASSISTED_AUTH) String auth, + @Assisted(ASSISTED_USER_ID) String userId, + @Assisted Context ctx, + @Assisted Runnable onNotAuthenticated) { logMethod(TAG, this); - this.userService = userService; + this.service = service; + this.auth = auth; + this.userId = userId; + this.ctx = ctx.getApplicationContext(); + this.onNotAuthenticated = onNotAuthenticated; + init(); } - public void fetchUserSubscribers(String auth, String userId, Activity activity) { - userService.getSubscribers(auth, userId).enqueue( - new BaseOnNotAuthenticatedCallback<>(activity, activity::recreate) { + public void init() { + service.getSubscribers(auth, userId).enqueue( + new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { @Override public void onResponse(Call> call, Response> resp) { super.onResponse(call, resp); - if (resp.code() == HttpCodes.OK) { - subscribersLiveData.setValue(resp.body()); + if (resp.code() != HttpCodes.OK || resp.body() == null) { return; } + subscribers.setValue(resp.body()); + return; } } ); } - public LiveData> getSubscribersLiveData() { - return subscribersLiveData; + public LiveData> getSubscribers() { + return subscribers; } } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserSubscriptionsViewModel.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserSubscriptionsViewModel.java index ca5db44..008c19d 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserSubscriptionsViewModel.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserSubscriptionsViewModel.java @@ -1,8 +1,10 @@ package com.tom.meeter.context.user.viewmodel; +import static com.tom.meeter.context.user.factory.AssistedFactoryBase.ASSISTED_AUTH; +import static com.tom.meeter.context.user.factory.AssistedFactoryBase.ASSISTED_USER_ID; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; -import android.app.Activity; +import android.content.Context; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; @@ -15,8 +17,8 @@ import java.util.List; -import javax.inject.Inject; - +import dagger.assisted.Assisted; +import dagger.assisted.AssistedInject; import retrofit2.Call; import retrofit2.Response; @@ -24,32 +26,47 @@ public class UserSubscriptionsViewModel extends ViewModel { private static final String TAG = UserSubscriptionsViewModel.class.getCanonicalName(); - private final MutableLiveData> subscriptionsLiveData = new MutableLiveData<>(); + private final UserService service; + private final String auth; + private final String userId; + private final Context ctx; + private final Runnable onNotAuthenticated; - private final UserService userService; + private final MutableLiveData> subscriptions = new MutableLiveData<>(); - @Inject - public UserSubscriptionsViewModel(UserService userService) { + @AssistedInject + public UserSubscriptionsViewModel( + UserService service, + @Assisted(ASSISTED_AUTH) String auth, + @Assisted(ASSISTED_USER_ID) String userId, + @Assisted Context ctx, + @Assisted Runnable onNotAuthenticated) { logMethod(TAG, this); - this.userService = userService; + this.service = service; + this.auth = auth; + this.userId = userId; + this.ctx = ctx.getApplicationContext(); + this.onNotAuthenticated = onNotAuthenticated; + init(); } - public void fetchUserSubscriptions(String auth, String userId, Activity activity) { - userService.getSubscriptions(auth, userId).enqueue( - new BaseOnNotAuthenticatedCallback<>(activity, activity::recreate) { + public void init() { + service.getSubscriptions(auth, userId).enqueue( + new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { @Override public void onResponse(Call> call, Response> resp) { super.onResponse(call, resp); - if (resp.code() == HttpCodes.OK) { - subscriptionsLiveData.setValue(resp.body()); + if (resp.code() != HttpCodes.OK || resp.body() == null) { return; } + subscriptions.setValue(resp.body()); + return; } } ); } - public LiveData> getSubscriptionsLiveData() { - return subscriptionsLiveData; + public LiveData> getSubscriptions() { + return subscriptions; } } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserViewModel.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserViewModel.java index 83ea792..fe7e46b 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserViewModel.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserViewModel.java @@ -1,8 +1,11 @@ package com.tom.meeter.context.user.viewmodel; +import static com.tom.meeter.context.user.factory.AssistedFactoryBase.ASSISTED_AUTH; +import static com.tom.meeter.context.user.factory.AssistedFactoryBase.ASSISTED_USER_ID; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; -import android.app.Activity; +import android.content.Context; +import android.graphics.Bitmap; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; @@ -12,14 +15,14 @@ import com.tom.meeter.context.network.dto.EventDTO; import com.tom.meeter.context.network.dto.UserDTO; import com.tom.meeter.context.user.service.UserService; +import com.tom.meeter.infrastructure.common.ImagesHelper; import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; import com.tom.meeter.infrastructure.http.HttpCodes; import java.util.List; -import javax.inject.Inject; - -import okhttp3.ResponseBody; +import dagger.assisted.Assisted; +import dagger.assisted.AssistedInject; import retrofit2.Call; import retrofit2.Response; @@ -27,67 +30,87 @@ public class UserViewModel extends ViewModel { private static final String TAG = UserViewModel.class.getCanonicalName(); - private final MutableLiveData userLiveData = new MutableLiveData<>(); - private final MutableLiveData amISubscriber = new MutableLiveData<>(); - private final MutableLiveData> userEventsLiveData = new MutableLiveData<>(); - private final MutableLiveData userPhotoLiveData = new MutableLiveData<>(); - - private final UserService userService; + private final UserService service; private final ImageDownloader imgDownloader; + private final String auth; + private final String userId; + private final Context ctx; + private final Runnable onNotAuthenticated; - @Inject + private final MutableLiveData user = new MutableLiveData<>(); + private final MutableLiveData amISubscriber = new MutableLiveData<>(); + private final MutableLiveData> events = new MutableLiveData<>(); + private final MutableLiveData photo = new MutableLiveData<>(); + + @AssistedInject public UserViewModel( - UserService userService, ImageDownloader imgDownloader) { + UserService service, ImageDownloader imgDownloader, + @Assisted(ASSISTED_AUTH) String auth, + @Assisted(ASSISTED_USER_ID) String userId, + @Assisted Context ctx, + @Assisted Runnable onNotAuthenticated) { logMethod(TAG, this); + this.service = service; this.imgDownloader = imgDownloader; - this.userService = userService; + this.auth = auth; + this.userId = userId; + this.ctx = ctx.getApplicationContext(); + this.onNotAuthenticated = onNotAuthenticated; + init(); } - public void fetchUserInformation(String auth, String userId, Activity activity) { - userService.getUser(auth, userId).enqueue( - new BaseOnNotAuthenticatedCallback<>(activity, activity::recreate) { + public void init() { + service.getUser(auth, userId).enqueue( + new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { @Override - public void onResponse(Call call, Response resp) { + public void onResponse( + Call call, Response resp) { super.onResponse(call, resp); - if (resp.code() == HttpCodes.OK) { - UserDTO user = resp.body(); - userLiveData.setValue(user); - String photoPath = user.getPhotoPath(); - if (photoPath == null) { - return; - } - imgDownloader.downloadUserImage( - photoPath, activity.getApplicationContext(), - userPhotoLiveData::setValue, - activity::recreate); + if (resp.code() != HttpCodes.OK || resp.body() == null) { + return; + } + UserDTO user = resp.body(); + UserViewModel.this.user.setValue(user); + String photoPath = user.getPhotoPath(); + if (photoPath == null) { return; } + imgDownloader.downloadUserImage( + photoPath, ctx, + ImagesHelper::bigCircleImage, + photo::setValue, + onNotAuthenticated); + return; } } ); - userService.amISubscribed(auth, userId).enqueue( - new BaseOnNotAuthenticatedCallback<>(activity, activity::recreate) { + service.amISubscribed(auth, userId).enqueue( + new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { @Override - public void onResponse(Call call, Response resp) { + public void onResponse( + Call call, Response resp) { super.onResponse(call, resp); - if (resp.code() == HttpCodes.OK) { - amISubscriber.setValue(resp.body()); + if (resp.code() != HttpCodes.OK) { return; } + amISubscriber.setValue(resp.body()); + return; } } ); - userService.getUserEvents(auth, userId).enqueue( - new BaseOnNotAuthenticatedCallback<>(activity, activity::recreate) { + service.getUserEvents(auth, userId).enqueue( + new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { @Override - public void onResponse(Call> call, Response> resp) { + public void onResponse( + Call> call, Response> resp) { super.onResponse(call, resp); - if (resp.code() == HttpCodes.OK) { - userEventsLiveData.setValue(resp.body()); + if (resp.code() != HttpCodes.OK) { return; } + events.setValue(resp.body()); + return; } }); } @@ -98,19 +121,19 @@ protected void onCleared() { super.onCleared(); } - public LiveData getUserLiveData() { - return userLiveData; + public LiveData getUser() { + return user; } - public LiveData> getUserEventsLiveData() { - return userEventsLiveData; + public LiveData> getEvents() { + return events; } public LiveData getAmISubscriber() { return amISubscriber; } - public LiveData getUserPhotoLiveData() { - return userPhotoLiveData; + public LiveData getPhoto() { + return photo; } } diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheSubscriberBinder.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheSubscriberBinder.java index 80d6081..e489c28 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheSubscriberBinder.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheSubscriberBinder.java @@ -10,6 +10,7 @@ import com.tom.meeter.context.image.ImageDownloader; import com.tom.meeter.context.network.dto.UserDTO; import com.tom.meeter.context.profile.subscriber.Subscriber; +import com.tom.meeter.infrastructure.common.ImagesHelper; import com.tom.meeter.infrastructure.components.adapter.OnSubscribeUnsubscribeClickListener; import com.tom.meeter.infrastructure.components.adapter.OnUserClickListener; import com.tom.meeter.infrastructure.components.viewholder.SubscriberViewHolder; @@ -63,11 +64,10 @@ public void bind(SubscriberViewHolder holder, Subscriber target) { return; } imageDownloader.downloadUserImage( - photoPath, ctx, + photoPath, ctx, ImagesHelper::circleImage, photo -> { - Bitmap circled = circleImage(photo); - holder.updatePhoto(circled); - imagesCache.put(photoPath, circled); + holder.updatePhoto(photo); + imagesCache.put(photoPath, photo); Log.d(TAG, "PhotoDownloaderWithCacheUserBinder: user " + "image downloaded for [" + photoPath + "], cache updated."); }, diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheUserBinder.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheUserBinder.java index 7eb8fb0..4206a1b 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheUserBinder.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheUserBinder.java @@ -1,6 +1,5 @@ package com.tom.meeter.infrastructure.components.binder; -import static com.tom.meeter.infrastructure.common.ImagesHelper.circleImage; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; import android.content.Context; @@ -9,6 +8,7 @@ import com.tom.meeter.context.image.ImageDownloader; import com.tom.meeter.context.network.dto.UserDTO; +import com.tom.meeter.infrastructure.common.ImagesHelper; import com.tom.meeter.infrastructure.components.adapter.OnUserClickListener; import com.tom.meeter.infrastructure.components.viewholder.UserViewHolder; @@ -53,11 +53,10 @@ public void bind(UserViewHolder holder, UserDTO user) { return; } imageDownloader.downloadUserImage( - photoPath, ctx, + photoPath, ctx, ImagesHelper::circleImage, photo -> { - Bitmap circled = circleImage(photo); - holder.updatePhoto(circled); - imagesCache.put(photoPath, circled); + holder.updatePhoto(photo); + imagesCache.put(photoPath, photo); Log.d(TAG, "PhotoDownloaderWithCacheUserBinder: user " + "image downloaded for [" + photoPath + "], cache updated."); }, diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/injection/viewmodel/ViewModelKey.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/injection/viewmodel/ViewModelKey.java deleted file mode 100644 index 822e2ff..0000000 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/injection/viewmodel/ViewModelKey.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.tom.meeter.infrastructure.injection.viewmodel; - -import androidx.lifecycle.ViewModel; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import dagger.MapKey; - -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -@MapKey -public @interface ViewModelKey { - Class value(); -} \ No newline at end of file From 452075b72b1b9c0d4f204c5359e6436f8ef4fcf8 Mon Sep 17 00:00:00 2001 From: Georgy Lebedik Date: Thu, 26 Jun 2025 22:24:54 +0300 Subject: [PATCH 12/32] Simplified code --- .../context/user/activity/UserActivity.java | 3 +-- .../user/activity/UserSubscribersActivity.java | 3 +-- .../user/activity/UserSubscriptionsActivity.java | 8 +++----- .../context/user/factory/AssistedFactoryBase.java | 9 +++------ .../UserSubscribersViewModelAssistedFactory.java | 10 ---------- ...UserSubscriptionsViewModelAssistedFactory.java | 10 ---------- .../factory/UserViewModelAssistedFactory.java | 10 ---------- .../user/viewmodel/UserSubscribersViewModel.java | 11 ++++------- .../viewmodel/UserSubscriptionsViewModel.java | 11 ++++------- .../context/user/viewmodel/UserViewModel.java | 15 ++++++--------- 10 files changed, 22 insertions(+), 68 deletions(-) diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java index 9796072..9a3ccf5 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java @@ -153,8 +153,7 @@ public void onResponse(Call call, Response resp) { viewModel = new ViewModelProvider( this, assistedFactory.factory( - assistedFactory, Globals.getAuthHeader(token), - userId, this, this::recreate)) + assistedFactory, userId, this, this::recreate)) .get(UserViewModel.class); binding.events.setLayoutManager(new GridLayoutManager(this, 2)); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscribersActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscribersActivity.java index 9349426..44f89ae 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscribersActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscribersActivity.java @@ -91,8 +91,7 @@ private void onInit(String token) { viewModel = new ViewModelProvider( this, assistedFactory.factory( - assistedFactory, Globals.getAuthHeader(token), - userId, this, this::recreate)) + assistedFactory, userId, this, this::recreate)) .get(UserSubscribersViewModel.class); viewModel.getSubscribers() diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscriptionsActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscriptionsActivity.java index 45fe749..30a2521 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscriptionsActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscriptionsActivity.java @@ -22,10 +22,9 @@ import com.tom.meeter.context.image.ImageDownloader; import com.tom.meeter.context.token.service.TokenService; import com.tom.meeter.context.user.adapter.UsersAdapter; -import com.tom.meeter.context.user.factory.UserViewModelAssistedFactory; +import com.tom.meeter.context.user.factory.UserSubscriptionsViewModelAssistedFactory; import com.tom.meeter.context.user.viewmodel.UserSubscriptionsViewModel; import com.tom.meeter.databinding.ActivityProfileSubscriptionsBinding; -import com.tom.meeter.infrastructure.common.Globals; import com.tom.meeter.infrastructure.components.binder.PhotoDownloaderWithCacheUserBinder; import javax.inject.Inject; @@ -37,7 +36,7 @@ public class UserSubscriptionsActivity extends AppCompatActivity { @Inject TokenService tokenService; @Inject - UserViewModelAssistedFactory assistedFactory; + UserSubscriptionsViewModelAssistedFactory assistedFactory; @Inject ImageDownloader imgDownloader; @@ -88,8 +87,7 @@ private void onInit(String token) { viewModel = new ViewModelProvider( this, assistedFactory.factory( - assistedFactory, Globals.getAuthHeader(token), userId, - this, this::recreate)) + assistedFactory, userId, this, this::recreate)) .get(UserSubscriptionsViewModel.class); binding.recyclerSubscriptions.setLayoutManager(new LinearLayoutManager(this)); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/AssistedFactoryBase.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/AssistedFactoryBase.java index c1bd4f1..eb3ff4b 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/AssistedFactoryBase.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/AssistedFactoryBase.java @@ -7,20 +7,17 @@ public interface AssistedFactoryBase { - String ASSISTED_AUTH = "assisted_auth"; - String ASSISTED_USER_ID = "assisted_user_id"; - - T create(String auth, String userId, Context ctx, Runnable onNotAuthenticated); + T create(String userId, Context ctx, Runnable onNotAuthenticated); default > ViewModelProvider.Factory factory( - F assistedFactory,String auth, String userId, Context ctx, + F assistedFactory, String userId, Context ctx, Runnable onNotAuthenticated) { return new ViewModelProvider.Factory() { @Override @SuppressWarnings("unchecked") //TODO associate T2 with T? public T2 create(Class modelClass) { - return (T2) assistedFactory.create(auth, userId, ctx, onNotAuthenticated); + return (T2) assistedFactory.create(userId, ctx, onNotAuthenticated); } }; } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscribersViewModelAssistedFactory.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscribersViewModelAssistedFactory.java index 23770ba..bcbadd7 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscribersViewModelAssistedFactory.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscribersViewModelAssistedFactory.java @@ -1,20 +1,10 @@ package com.tom.meeter.context.user.factory; -import android.content.Context; - import com.tom.meeter.context.user.viewmodel.UserSubscribersViewModel; -import dagger.assisted.Assisted; import dagger.assisted.AssistedFactory; @AssistedFactory public interface UserSubscribersViewModelAssistedFactory extends AssistedFactoryBase { - - @Override - UserSubscribersViewModel create( - @Assisted(ASSISTED_AUTH) String auth, - @Assisted(ASSISTED_USER_ID) String userId, - Context ctx, - Runnable onNotAuthenticated); } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscriptionsViewModelAssistedFactory.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscriptionsViewModelAssistedFactory.java index 2e04968..c06c2ca 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscriptionsViewModelAssistedFactory.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscriptionsViewModelAssistedFactory.java @@ -1,20 +1,10 @@ package com.tom.meeter.context.user.factory; -import android.content.Context; - import com.tom.meeter.context.user.viewmodel.UserSubscriptionsViewModel; -import dagger.assisted.Assisted; import dagger.assisted.AssistedFactory; @AssistedFactory public interface UserSubscriptionsViewModelAssistedFactory extends AssistedFactoryBase { - - @Override - UserSubscriptionsViewModel create( - @Assisted(ASSISTED_AUTH) String auth, - @Assisted(ASSISTED_USER_ID) String userId, - Context ctx, - Runnable onNotAuthenticated); } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserViewModelAssistedFactory.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserViewModelAssistedFactory.java index 0527ced..98d83f1 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserViewModelAssistedFactory.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserViewModelAssistedFactory.java @@ -1,20 +1,10 @@ package com.tom.meeter.context.user.factory; -import android.content.Context; - import com.tom.meeter.context.user.viewmodel.UserViewModel; -import dagger.assisted.Assisted; import dagger.assisted.AssistedFactory; @AssistedFactory public interface UserViewModelAssistedFactory extends AssistedFactoryBase { - - @Override - UserViewModel create( - @Assisted(ASSISTED_AUTH) String auth, - @Assisted(ASSISTED_USER_ID) String userId, - Context ctx, - Runnable onNotAuthenticated); } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserSubscribersViewModel.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserSubscribersViewModel.java index 848cde5..bf1757a 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserSubscribersViewModel.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserSubscribersViewModel.java @@ -1,9 +1,9 @@ package com.tom.meeter.context.user.viewmodel; -import static com.tom.meeter.context.user.factory.AssistedFactoryBase.ASSISTED_AUTH; -import static com.tom.meeter.context.user.factory.AssistedFactoryBase.ASSISTED_USER_ID; +import static com.tom.meeter.context.auth.infrastructure.AuthHelper.getAuthHeader; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; +import android.accounts.AccountManager; import android.content.Context; import androidx.lifecycle.LiveData; @@ -27,7 +27,6 @@ public class UserSubscribersViewModel extends ViewModel { private static final String TAG = UserSubscribersViewModel.class.getCanonicalName(); private final UserService service; - private final String auth; private final String userId; private final Context ctx; private final Runnable onNotAuthenticated; @@ -37,13 +36,11 @@ public class UserSubscribersViewModel extends ViewModel { @AssistedInject public UserSubscribersViewModel( UserService service, - @Assisted(ASSISTED_AUTH) String auth, - @Assisted(ASSISTED_USER_ID) String userId, + @Assisted String userId, @Assisted Context ctx, @Assisted Runnable onNotAuthenticated) { logMethod(TAG, this); this.service = service; - this.auth = auth; this.userId = userId; this.ctx = ctx.getApplicationContext(); this.onNotAuthenticated = onNotAuthenticated; @@ -51,7 +48,7 @@ public UserSubscribersViewModel( } public void init() { - service.getSubscribers(auth, userId).enqueue( + service.getSubscribers(getAuthHeader(AccountManager.get(ctx)), userId).enqueue( new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { @Override public void onResponse(Call> call, Response> resp) { diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserSubscriptionsViewModel.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserSubscriptionsViewModel.java index 008c19d..4b21784 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserSubscriptionsViewModel.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserSubscriptionsViewModel.java @@ -1,9 +1,9 @@ package com.tom.meeter.context.user.viewmodel; -import static com.tom.meeter.context.user.factory.AssistedFactoryBase.ASSISTED_AUTH; -import static com.tom.meeter.context.user.factory.AssistedFactoryBase.ASSISTED_USER_ID; +import static com.tom.meeter.context.auth.infrastructure.AuthHelper.getAuthHeader; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; +import android.accounts.AccountManager; import android.content.Context; import androidx.lifecycle.LiveData; @@ -27,7 +27,6 @@ public class UserSubscriptionsViewModel extends ViewModel { private static final String TAG = UserSubscriptionsViewModel.class.getCanonicalName(); private final UserService service; - private final String auth; private final String userId; private final Context ctx; private final Runnable onNotAuthenticated; @@ -37,13 +36,11 @@ public class UserSubscriptionsViewModel extends ViewModel { @AssistedInject public UserSubscriptionsViewModel( UserService service, - @Assisted(ASSISTED_AUTH) String auth, - @Assisted(ASSISTED_USER_ID) String userId, + @Assisted String userId, @Assisted Context ctx, @Assisted Runnable onNotAuthenticated) { logMethod(TAG, this); this.service = service; - this.auth = auth; this.userId = userId; this.ctx = ctx.getApplicationContext(); this.onNotAuthenticated = onNotAuthenticated; @@ -51,7 +48,7 @@ public UserSubscriptionsViewModel( } public void init() { - service.getSubscriptions(auth, userId).enqueue( + service.getSubscriptions(getAuthHeader(AccountManager.get(ctx)), userId).enqueue( new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { @Override public void onResponse(Call> call, Response> resp) { diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserViewModel.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserViewModel.java index fe7e46b..ee64d11 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserViewModel.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/viewmodel/UserViewModel.java @@ -1,9 +1,9 @@ package com.tom.meeter.context.user.viewmodel; -import static com.tom.meeter.context.user.factory.AssistedFactoryBase.ASSISTED_AUTH; -import static com.tom.meeter.context.user.factory.AssistedFactoryBase.ASSISTED_USER_ID; +import static com.tom.meeter.context.auth.infrastructure.AuthHelper.getAuthHeader; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; +import android.accounts.AccountManager; import android.content.Context; import android.graphics.Bitmap; @@ -32,7 +32,6 @@ public class UserViewModel extends ViewModel { private final UserService service; private final ImageDownloader imgDownloader; - private final String auth; private final String userId; private final Context ctx; private final Runnable onNotAuthenticated; @@ -45,14 +44,12 @@ public class UserViewModel extends ViewModel { @AssistedInject public UserViewModel( UserService service, ImageDownloader imgDownloader, - @Assisted(ASSISTED_AUTH) String auth, - @Assisted(ASSISTED_USER_ID) String userId, + @Assisted String userId, @Assisted Context ctx, @Assisted Runnable onNotAuthenticated) { logMethod(TAG, this); this.service = service; this.imgDownloader = imgDownloader; - this.auth = auth; this.userId = userId; this.ctx = ctx.getApplicationContext(); this.onNotAuthenticated = onNotAuthenticated; @@ -60,7 +57,7 @@ public UserViewModel( } public void init() { - service.getUser(auth, userId).enqueue( + service.getUser(getAuthHeader(AccountManager.get(ctx)), userId).enqueue( new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { @Override public void onResponse( @@ -85,7 +82,7 @@ public void onResponse( } ); - service.amISubscribed(auth, userId).enqueue( + service.amISubscribed(getAuthHeader(AccountManager.get(ctx)), userId).enqueue( new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { @Override public void onResponse( @@ -100,7 +97,7 @@ public void onResponse( } ); - service.getUserEvents(auth, userId).enqueue( + service.getUserEvents(getAuthHeader(AccountManager.get(ctx)), userId).enqueue( new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { @Override public void onResponse( From b96dbca83b55c0b3c042c063ed8f2bc52f7f95d1 Mon Sep 17 00:00:00 2001 From: Georgy Lebedik Date: Thu, 26 Jun 2025 22:30:42 +0300 Subject: [PATCH 13/32] Moved old classes --- .../main/java/com/tom/meeter/AppModule.java | 8 +- .../context/profile/event/domain/Event.java | 115 ------------------ .../event/database/EventDao.java | 4 +- .../event/database/EventDatabase.java | 4 +- .../repository/event/domain/Event.java | 115 ++++++++++++++++++ .../event/repository/EventRepository.java | 8 +- .../event/service/EventService.java | 2 +- .../user/database/UserDao.java | 4 +- .../user/database/UserDatabase.java | 4 +- .../{ => repository}/user/domain/User.java | 2 +- .../user/repository/UserRepository.java | 6 +- .../viewmodel/UserEventsViewModel.java | 4 +- .../viewmodel/UserProfileViewModel.java | 4 +- 13 files changed, 140 insertions(+), 140 deletions(-) delete mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/profile/event/domain/Event.java rename AndroidClient/src/main/java/com/tom/meeter/context/profile/{ => repository}/event/database/EventDao.java (87%) rename AndroidClient/src/main/java/com/tom/meeter/context/profile/{ => repository}/event/database/EventDatabase.java (61%) create mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/event/domain/Event.java rename AndroidClient/src/main/java/com/tom/meeter/context/profile/{ => repository}/event/repository/EventRepository.java (87%) rename AndroidClient/src/main/java/com/tom/meeter/context/profile/{ => repository}/event/service/EventService.java (89%) rename AndroidClient/src/main/java/com/tom/meeter/context/profile/{ => repository}/user/database/UserDao.java (78%) rename AndroidClient/src/main/java/com/tom/meeter/context/profile/{ => repository}/user/database/UserDatabase.java (62%) rename AndroidClient/src/main/java/com/tom/meeter/context/profile/{ => repository}/user/domain/User.java (96%) rename AndroidClient/src/main/java/com/tom/meeter/context/profile/{ => repository}/user/repository/UserRepository.java (90%) diff --git a/AndroidClient/src/main/java/com/tom/meeter/AppModule.java b/AndroidClient/src/main/java/com/tom/meeter/AppModule.java index 9e1effd..80b3f01 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/AppModule.java +++ b/AndroidClient/src/main/java/com/tom/meeter/AppModule.java @@ -13,12 +13,12 @@ import com.fasterxml.jackson.databind.json.JsonMapper; import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import com.tom.meeter.context.profile.event.database.EventDao; -import com.tom.meeter.context.profile.event.database.EventDatabase; +import com.tom.meeter.context.profile.repository.event.database.EventDao; +import com.tom.meeter.context.profile.repository.event.database.EventDatabase; +import com.tom.meeter.context.profile.repository.user.database.UserDao; +import com.tom.meeter.context.profile.repository.user.database.UserDatabase; import com.tom.meeter.context.profile.service.ProfileService; import com.tom.meeter.context.profile.settings.service.SettingsService; -import com.tom.meeter.context.profile.user.database.UserDao; -import com.tom.meeter.context.profile.user.database.UserDatabase; import com.tom.meeter.infrastructure.http.HttpClient; import java.util.TimeZone; diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/event/domain/Event.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/event/domain/Event.java deleted file mode 100644 index c594f0e..0000000 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/event/domain/Event.java +++ /dev/null @@ -1,115 +0,0 @@ -package com.tom.meeter.context.profile.event.domain; - -import static androidx.room.ForeignKey.CASCADE; - -import androidx.annotation.NonNull; -import androidx.room.Entity; -import androidx.room.ForeignKey; -import androidx.room.PrimaryKey; - -import com.tom.meeter.context.profile.user.domain.User; - -@Entity -public class Event { - - @PrimaryKey - @NonNull - private String id; - private String name; - private String description; - private double latitude; - private double longitude; - - @ForeignKey(entity = User.class, parentColumns = "id", childColumns = "creatorId", - onDelete = CASCADE) - private String creatorId; - private String created; - private String starting; - private String ending; - - public Event(@NonNull String id, String name, String description, double latitude, - double longitude, String creatorId, String created, String starting, - String ending) { - this.id = id; - this.name = name; - this.description = description; - this.latitude = latitude; - this.longitude = longitude; - this.creatorId = creatorId; - this.created = created; - this.starting = starting; - this.ending = ending; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public double getLatitude() { - return latitude; - } - - public void setLatitude(double latitude) { - this.latitude = latitude; - } - - public double getLongitude() { - return longitude; - } - - public void setLongitude(double longitude) { - this.longitude = longitude; - } - - public String getCreatorId() { - return creatorId; - } - - public void setCreatorId(String creatorId) { - this.creatorId = creatorId; - } - - public String getCreated() { - return created; - } - - public void setCreated(String created) { - this.created = created; - } - - public String getStarting() { - return starting; - } - - public void setStarting(String starting) { - this.starting = starting; - } - - public String getEnding() { - return ending; - } - - public void setEnding(String ending) { - this.ending = ending; - } -} diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/event/database/EventDao.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/event/database/EventDao.java similarity index 87% rename from AndroidClient/src/main/java/com/tom/meeter/context/profile/event/database/EventDao.java rename to AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/event/database/EventDao.java index 0ad18c6..9c8b87f 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/event/database/EventDao.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/event/database/EventDao.java @@ -1,4 +1,4 @@ -package com.tom.meeter.context.profile.event.database; +package com.tom.meeter.context.profile.repository.event.database; import static androidx.room.OnConflictStrategy.REPLACE; @@ -7,7 +7,7 @@ import androidx.room.Insert; import androidx.room.Query; -import com.tom.meeter.context.profile.event.domain.Event; +import com.tom.meeter.context.profile.repository.event.domain.Event; import java.util.List; diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/event/database/EventDatabase.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/event/database/EventDatabase.java similarity index 61% rename from AndroidClient/src/main/java/com/tom/meeter/context/profile/event/database/EventDatabase.java rename to AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/event/database/EventDatabase.java index 3d463cf..3dd122d 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/event/database/EventDatabase.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/event/database/EventDatabase.java @@ -1,9 +1,9 @@ -package com.tom.meeter.context.profile.event.database; +package com.tom.meeter.context.profile.repository.event.database; import androidx.room.Database; import androidx.room.RoomDatabase; -import com.tom.meeter.context.profile.event.domain.Event; +import com.tom.meeter.context.profile.repository.event.domain.Event; @Database(entities = {Event.class}, version = 1) public abstract class EventDatabase extends RoomDatabase { diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/event/domain/Event.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/event/domain/Event.java new file mode 100644 index 0000000..fca3c8d --- /dev/null +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/event/domain/Event.java @@ -0,0 +1,115 @@ +package com.tom.meeter.context.profile.repository.event.domain; + +import static androidx.room.ForeignKey.CASCADE; + +import androidx.annotation.NonNull; +import androidx.room.Entity; +import androidx.room.ForeignKey; +import androidx.room.PrimaryKey; + +import com.tom.meeter.context.profile.repository.user.domain.User; + +@Entity +public class Event { + + @PrimaryKey + @NonNull + private String id; + private String name; + private String description; + private double latitude; + private double longitude; + + @ForeignKey(entity = User.class, parentColumns = "id", childColumns = "creatorId", + onDelete = CASCADE) + private String creatorId; + private String created; + private String starting; + private String ending; + + public Event(@NonNull String id, String name, String description, double latitude, + double longitude, String creatorId, String created, String starting, + String ending) { + this.id = id; + this.name = name; + this.description = description; + this.latitude = latitude; + this.longitude = longitude; + this.creatorId = creatorId; + this.created = created; + this.starting = starting; + this.ending = ending; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public double getLatitude() { + return latitude; + } + + public void setLatitude(double latitude) { + this.latitude = latitude; + } + + public double getLongitude() { + return longitude; + } + + public void setLongitude(double longitude) { + this.longitude = longitude; + } + + public String getCreatorId() { + return creatorId; + } + + public void setCreatorId(String creatorId) { + this.creatorId = creatorId; + } + + public String getCreated() { + return created; + } + + public void setCreated(String created) { + this.created = created; + } + + public String getStarting() { + return starting; + } + + public void setStarting(String starting) { + this.starting = starting; + } + + public String getEnding() { + return ending; + } + + public void setEnding(String ending) { + this.ending = ending; + } +} diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/event/repository/EventRepository.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/event/repository/EventRepository.java similarity index 87% rename from AndroidClient/src/main/java/com/tom/meeter/context/profile/event/repository/EventRepository.java rename to AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/event/repository/EventRepository.java index 0f1fa67..7622bd7 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/event/repository/EventRepository.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/event/repository/EventRepository.java @@ -1,13 +1,13 @@ -package com.tom.meeter.context.profile.event.repository; +package com.tom.meeter.context.profile.repository.event.repository; import android.util.Log; import androidx.lifecycle.LiveData; import com.tom.meeter.context.network.dto.EventDTO; -import com.tom.meeter.context.profile.event.database.EventDao; -import com.tom.meeter.context.profile.event.domain.Event; -import com.tom.meeter.context.profile.event.service.EventService; +import com.tom.meeter.context.profile.repository.event.database.EventDao; +import com.tom.meeter.context.profile.repository.event.domain.Event; +import com.tom.meeter.context.profile.repository.event.service.EventService; import java.io.IOException; import java.util.ArrayList; diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/event/service/EventService.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/event/service/EventService.java similarity index 89% rename from AndroidClient/src/main/java/com/tom/meeter/context/profile/event/service/EventService.java rename to AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/event/service/EventService.java index 04c7b6c..ffacf1d 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/event/service/EventService.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/event/service/EventService.java @@ -1,4 +1,4 @@ -package com.tom.meeter.context.profile.event.service; +package com.tom.meeter.context.profile.repository.event.service; import com.tom.meeter.context.network.dto.EventDTO; diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/user/database/UserDao.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/user/database/UserDao.java similarity index 78% rename from AndroidClient/src/main/java/com/tom/meeter/context/profile/user/database/UserDao.java rename to AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/user/database/UserDao.java index 5996bf9..1d468e0 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/user/database/UserDao.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/user/database/UserDao.java @@ -1,4 +1,4 @@ -package com.tom.meeter.context.profile.user.database; +package com.tom.meeter.context.profile.repository.user.database; import static androidx.room.OnConflictStrategy.REPLACE; @@ -7,7 +7,7 @@ import androidx.room.Insert; import androidx.room.Query; -import com.tom.meeter.context.profile.user.domain.User; +import com.tom.meeter.context.profile.repository.user.domain.User; import io.reactivex.Maybe; diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/user/database/UserDatabase.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/user/database/UserDatabase.java similarity index 62% rename from AndroidClient/src/main/java/com/tom/meeter/context/profile/user/database/UserDatabase.java rename to AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/user/database/UserDatabase.java index 9e5c830..f9c7fd0 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/user/database/UserDatabase.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/user/database/UserDatabase.java @@ -1,9 +1,9 @@ -package com.tom.meeter.context.profile.user.database; +package com.tom.meeter.context.profile.repository.user.database; import androidx.room.Database; import androidx.room.RoomDatabase; -import com.tom.meeter.context.profile.user.domain.User; +import com.tom.meeter.context.profile.repository.user.domain.User; @Database(entities = {User.class}, version = 2) public abstract class UserDatabase extends RoomDatabase { diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/user/domain/User.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/user/domain/User.java similarity index 96% rename from AndroidClient/src/main/java/com/tom/meeter/context/profile/user/domain/User.java rename to AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/user/domain/User.java index 48f49fa..6632424 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/user/domain/User.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/user/domain/User.java @@ -1,4 +1,4 @@ -package com.tom.meeter.context.profile.user.domain; +package com.tom.meeter.context.profile.repository.user.domain; import androidx.annotation.NonNull; import androidx.room.Entity; diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/user/repository/UserRepository.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/user/repository/UserRepository.java similarity index 90% rename from AndroidClient/src/main/java/com/tom/meeter/context/profile/user/repository/UserRepository.java rename to AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/user/repository/UserRepository.java index d0015f6..1be57a4 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/user/repository/UserRepository.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/user/repository/UserRepository.java @@ -1,12 +1,12 @@ -package com.tom.meeter.context.profile.user.repository; +package com.tom.meeter.context.profile.repository.user.repository; import android.util.Log; import androidx.lifecycle.LiveData; import com.tom.meeter.context.network.dto.UserDTO; -import com.tom.meeter.context.profile.user.database.UserDao; -import com.tom.meeter.context.profile.user.domain.User; +import com.tom.meeter.context.profile.repository.user.database.UserDao; +import com.tom.meeter.context.profile.repository.user.domain.User; import com.tom.meeter.context.user.service.UserService; import java.time.LocalDate; diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/UserEventsViewModel.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/UserEventsViewModel.java index 158ee14..b97fc21 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/UserEventsViewModel.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/UserEventsViewModel.java @@ -3,8 +3,8 @@ import androidx.lifecycle.LiveData; import androidx.lifecycle.ViewModel; -import com.tom.meeter.context.profile.event.domain.Event; -import com.tom.meeter.context.profile.event.repository.EventRepository; +import com.tom.meeter.context.profile.repository.event.domain.Event; +import com.tom.meeter.context.profile.repository.event.repository.EventRepository; import java.util.List; diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/UserProfileViewModel.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/UserProfileViewModel.java index 36f2082..a0fbbfc 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/UserProfileViewModel.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/UserProfileViewModel.java @@ -5,8 +5,8 @@ import androidx.lifecycle.LiveData; import androidx.lifecycle.ViewModel; -import com.tom.meeter.context.profile.user.domain.User; -import com.tom.meeter.context.profile.user.repository.UserRepository; +import com.tom.meeter.context.profile.repository.user.domain.User; +import com.tom.meeter.context.profile.repository.user.repository.UserRepository; @Deprecated public class UserProfileViewModel extends ViewModel { From af40d3817b4601b3cd99b53a3dceb1f12abf52e2 Mon Sep 17 00:00:00 2001 From: Georgy Lebedik Date: Thu, 26 Jun 2025 23:37:54 +0300 Subject: [PATCH 14/32] Refactoring --- .../profile/activity/SubscribersActivity.java | 18 +++----- .../activity/SubscriptionsActivity.java | 14 +++--- .../profile/adapter/SubscribersAdapter.java | 38 ++++++++++------ .../adapter/BaseSubscriberAdapter.java | 2 +- .../OnSubscribeUnsubscribeClickListener.java | 2 +- .../binder/BaseSubscriberBinder.java | 11 +++++ ...toDownloaderWithCacheSubscriberBinder.java | 43 +++++++++++++------ .../components/binder/SubscriberBinder.java | 10 +++-- 8 files changed, 86 insertions(+), 52 deletions(-) create mode 100644 AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/BaseSubscriberBinder.java diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscribersActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscribersActivity.java index c3e8bad..3dd7bab 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscribersActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscribersActivity.java @@ -17,7 +17,6 @@ import com.tom.meeter.context.image.ImageDownloader; import com.tom.meeter.context.profile.adapter.SubscribersAdapter; import com.tom.meeter.context.profile.factory.ProfileSubscribersViewModelAssistedFactory; -import com.tom.meeter.context.profile.service.ProfileService; import com.tom.meeter.context.profile.viewmodel.ProfileSubscribersViewModel; import com.tom.meeter.context.token.service.TokenService; import com.tom.meeter.context.user.service.UserService; @@ -30,8 +29,6 @@ public class SubscribersActivity extends AppCompatActivity { private static final String TAG = SubscribersActivity.class.getCanonicalName(); - @Inject - ProfileService profileService; @Inject TokenService tokenService; @Inject @@ -39,8 +36,9 @@ public class SubscribersActivity extends AppCompatActivity { @Inject ImageDownloader imgDownloader; @Inject - UserService userService; + UserService service; + private final Runnable onAuthFail = this::recreate; private AccountManager accountManager; private ActivityProfileSubscribersBinding binding; private SubscribersAdapter adapter; @@ -69,22 +67,16 @@ private void onInit(String token) { String auth = getAuthHeader(accountManager); adapter = new SubscribersAdapter( + service, onAuthFail, this, new PhotoDownloaderWithCacheSubscriberBinder( - this, imgDownloader, - (user) -> dispatchToUserActivity(this, user.getId()), - (sub, pos) -> adapter.onSubUnsubClick( - userService, sub, pos, this::recreate, this, auth), - this::recreate - )); + this, imgDownloader, onAuthFail)); binding.recyclerSubscribers.setLayoutManager(new LinearLayoutManager(this)); binding.recyclerSubscribers.setAdapter(adapter); viewModel = new ViewModelProvider( this, - assistedFactory.factory( - assistedFactory, auth, this, - this::recreate)) + assistedFactory.factory(assistedFactory, auth, this, onAuthFail)) .get(ProfileSubscribersViewModel.class); viewModel.getSubscribers() diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscriptionsActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscriptionsActivity.java index 3efd74a..f44310a 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscriptionsActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscriptionsActivity.java @@ -38,6 +38,7 @@ public class SubscriptionsActivity extends AppCompatActivity { @Inject UserService userService; + private final Runnable onAuthFail = this::recreate; private ActivityProfileSubscriptionsBinding binding; private AccountManager accountManager; private SubscribersAdapter adapter; @@ -65,23 +66,18 @@ private void onInit(String token) { setContentView(view); String auth = getAuthHeader(accountManager); + adapter = new SubscribersAdapter( + userService, onAuthFail, this, new PhotoDownloaderWithCacheSubscriberBinder( - this, imgDownloader, - (e) -> dispatchToUserActivity(this, e.getId()), - (sub, pos) -> adapter.onSubUnsubClick( - userService, sub, pos, this::recreate, this, auth), - this::recreate - )); + this, imgDownloader, onAuthFail)); binding.recyclerSubscriptions.setLayoutManager(new LinearLayoutManager(this)); binding.recyclerSubscriptions.setAdapter(adapter); viewModel = new ViewModelProvider( this, - assistedFactory.factory( - assistedFactory, auth, this, - this::recreate)) + assistedFactory.factory(assistedFactory, auth, this, onAuthFail)) .get(ProfileSubscriptionsViewModel.class); viewModel.getSubscriptions() diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/adapter/SubscribersAdapter.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/adapter/SubscribersAdapter.java index fb4ef17..89ebf33 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/adapter/SubscribersAdapter.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/adapter/SubscribersAdapter.java @@ -1,7 +1,10 @@ package com.tom.meeter.context.profile.adapter; +import static com.tom.meeter.context.auth.infrastructure.AuthHelper.getAuthHeader; +import static com.tom.meeter.context.user.activity.UserActivity.dispatchToUserActivity; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; +import android.accounts.AccountManager; import android.content.Context; import android.view.LayoutInflater; import android.view.ViewGroup; @@ -24,9 +27,20 @@ public class SubscribersAdapter extends BaseSubscriberAdapter binder) { + private final UserService service; + private final Runnable onAuthFail; + private final Context ctx; + + public SubscribersAdapter( + UserService service, Runnable onAuthFail, Context ctx, + SubscriberBinder binder) { super(binder); + binder.setup( + this::onSubUnSubClick, user -> dispatchToUserActivity(ctx, user.getId())); logMethod(TAG, this); + this.service = service; + this.onAuthFail = onAuthFail; + this.ctx = ctx; } @Override @@ -43,31 +57,31 @@ public void onAttachedToRecyclerView(RecyclerView recyclerView) { logMethod(TAG, this); } - public void onSubUnsubClick( - UserService service, Subscriber sub, int position, - Runnable onAuthFail, Context ctx, String auth) { + public void onSubUnSubClick(Subscriber sub, int position) { if (sub.isAmISubscribedTo()) { - service.unsubscribe(auth, sub.getUser().getId()) + service.unsubscribe(getAuthHeader(AccountManager.get(ctx)), sub.getUser().getId()) .enqueue(new BaseOnNotAuthenticatedCallback<>(ctx, onAuthFail) { @Override public void onResponse(Call call, Response resp) { super.onResponse(call, resp); - if (resp.code() == HttpCodes.OK) { - sub.setAmISubscribedTo(false); - SubscribersAdapter.this.notifyItemChanged(position); + if (resp.code() != HttpCodes.OK) { + return; } + sub.setAmISubscribedTo(false); + SubscribersAdapter.this.notifyItemChanged(position); } }); } else { - service.subscribe(auth, sub.getUser().getId()) + service.subscribe(getAuthHeader(AccountManager.get(ctx)), sub.getUser().getId()) .enqueue(new BaseOnNotAuthenticatedCallback<>(ctx, onAuthFail) { @Override public void onResponse(Call call, Response resp) { super.onResponse(call, resp); - if (resp.code() == HttpCodes.OK) { - sub.setAmISubscribedTo(true); - SubscribersAdapter.this.notifyItemChanged(position); + if (resp.code() != HttpCodes.OK) { + return; } + sub.setAmISubscribedTo(true); + SubscribersAdapter.this.notifyItemChanged(position); } }); } diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/BaseSubscriberAdapter.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/BaseSubscriberAdapter.java index b439362..01209aa 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/BaseSubscriberAdapter.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/BaseSubscriberAdapter.java @@ -13,7 +13,7 @@ public abstract class BaseSubscriberAdapter extends RecyclerView.Adapter { - private final SubscriberBinder binder; + protected final SubscriberBinder binder; protected final List subs = new ArrayList<>(); protected BaseSubscriberAdapter(SubscriberBinder binder) { diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/OnSubscribeUnsubscribeClickListener.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/OnSubscribeUnsubscribeClickListener.java index d37fad7..57bcc0b 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/OnSubscribeUnsubscribeClickListener.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/OnSubscribeUnsubscribeClickListener.java @@ -3,5 +3,5 @@ import com.tom.meeter.context.profile.subscriber.Subscriber; public interface OnSubscribeUnsubscribeClickListener { - void onSubUnsub(Subscriber sub, int position); + void onSubUnSub(Subscriber sub, int position); } diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/BaseSubscriberBinder.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/BaseSubscriberBinder.java new file mode 100644 index 0000000..cc46c53 --- /dev/null +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/BaseSubscriberBinder.java @@ -0,0 +1,11 @@ +package com.tom.meeter.infrastructure.components.binder; + +import androidx.recyclerview.widget.RecyclerView; + +import com.tom.meeter.context.profile.subscriber.Subscriber; + +public interface BaseSubscriberBinder + extends BaseViewHolderBinder { + + void bind(T holder, Subscriber target); +} diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheSubscriberBinder.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheSubscriberBinder.java index e489c28..ede0695 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheSubscriberBinder.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheSubscriberBinder.java @@ -1,6 +1,5 @@ package com.tom.meeter.infrastructure.components.binder; -import static com.tom.meeter.infrastructure.common.ImagesHelper.circleImage; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; import android.content.Context; @@ -18,30 +17,36 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -public class PhotoDownloaderWithCacheSubscriberBinder implements SubscriberBinder { +public class PhotoDownloaderWithCacheSubscriberBinder + implements SubscriberBinder { private static final String TAG = PhotoDownloaderWithCacheSubscriberBinder.class.getCanonicalName(); private final Context ctx; private final ImageDownloader imageDownloader; - private final OnUserClickListener userClickListener; - private final OnSubscribeUnsubscribeClickListener subUnsubClickListener; private final Runnable onAuthFail; private final Map imagesCache = new ConcurrentHashMap<>(); + private OnUserClickListener userClickListener; + private OnSubscribeUnsubscribeClickListener subUnSubClickListener; + public PhotoDownloaderWithCacheSubscriberBinder( Context ctx, ImageDownloader imgDownloader, - OnUserClickListener listener, - OnSubscribeUnsubscribeClickListener subUnsubClickListener, Runnable onAuthFail) { logMethod(TAG, this); this.ctx = ctx; this.imageDownloader = imgDownloader; - this.userClickListener = listener; - this.subUnsubClickListener = subUnsubClickListener; this.onAuthFail = onAuthFail; } + @Override + public void setup( + OnSubscribeUnsubscribeClickListener subUnSubClickListener, + OnUserClickListener userClickListener) { + this.subUnSubClickListener = subUnSubClickListener; + this.userClickListener = userClickListener; + } + @Override public void bind(SubscriberViewHolder holder, Subscriber target) { UserDTO user = target.getUser(); @@ -50,16 +55,18 @@ public void bind(SubscriberViewHolder holder, Subscriber target) { holder.bind( target.isAmISubscribedTo(), user.getName(), user.getSurname(), null, - (v) -> userClickListener.onClick(user), - (v) -> subUnsubClickListener.onSubUnsub(target, holder.getBindingAdapterPosition())); + (v) -> sendUserClickEvent(user), + (v) -> sendSubUnSubEvent(target, holder) + ); return; } Bitmap circledPhotoCache = imagesCache.get(photoPath); holder.bind( target.isAmISubscribedTo(), user.getName(), user.getSurname(), circledPhotoCache, - (v) -> userClickListener.onClick(user), - (v) -> subUnsubClickListener.onSubUnsub(target, holder.getBindingAdapterPosition())); + (v) -> sendUserClickEvent(user), + (v) -> sendSubUnSubEvent(target, holder) + ); if (circledPhotoCache != null) { return; } @@ -73,4 +80,16 @@ public void bind(SubscriberViewHolder holder, Subscriber target) { }, onAuthFail); } + + private void sendUserClickEvent(UserDTO user) { + if (userClickListener != null) { + userClickListener.onClick(user); + } + } + + private void sendSubUnSubEvent(Subscriber sub, SubscriberViewHolder holder) { + if (subUnSubClickListener != null) { + subUnSubClickListener.onSubUnSub(sub, holder.getBindingAdapterPosition()); + } + } } diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/SubscriberBinder.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/SubscriberBinder.java index 18d653d..eec7566 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/SubscriberBinder.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/SubscriberBinder.java @@ -2,10 +2,12 @@ import androidx.recyclerview.widget.RecyclerView; -import com.tom.meeter.context.profile.subscriber.Subscriber; +import com.tom.meeter.infrastructure.components.adapter.OnSubscribeUnsubscribeClickListener; +import com.tom.meeter.infrastructure.components.adapter.OnUserClickListener; public interface SubscriberBinder - extends BaseViewHolderBinder { - - void bind(T holder, Subscriber target); + extends BaseSubscriberBinder { + void setup( + OnSubscribeUnsubscribeClickListener subUnSubClickListener, + OnUserClickListener userClickListener); } From ac6d0350c515028cec50c88dc5b997ca300f9064 Mon Sep 17 00:00:00 2001 From: Georgy Lebedik Date: Fri, 27 Jun 2025 00:29:41 +0300 Subject: [PATCH 15/32] Refactoring --- .../network/dto/BaseNetworkEntity.java | 5 ++ .../meeter/context/network/dto/EventDTO.java | 3 +- .../meeter/context/network/dto/UserDTO.java | 3 +- .../profile/subscriber/Subscriber.java | 8 ++- .../components/adapter/BaseAdapter.java | 72 +++++++++++++++++++ .../components/adapter/BaseEventAdapter.java | 64 +---------------- .../adapter/BaseSubscriberAdapter.java | 64 +---------------- .../components/adapter/BaseUserAdapter.java | 64 +---------------- 8 files changed, 97 insertions(+), 186 deletions(-) create mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/network/dto/BaseNetworkEntity.java create mode 100644 AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/BaseAdapter.java diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/network/dto/BaseNetworkEntity.java b/AndroidClient/src/main/java/com/tom/meeter/context/network/dto/BaseNetworkEntity.java new file mode 100644 index 0000000..ee0c885 --- /dev/null +++ b/AndroidClient/src/main/java/com/tom/meeter/context/network/dto/BaseNetworkEntity.java @@ -0,0 +1,5 @@ +package com.tom.meeter.context.network.dto; + +public interface BaseNetworkEntity { + String getId(); +} diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/network/dto/EventDTO.java b/AndroidClient/src/main/java/com/tom/meeter/context/network/dto/EventDTO.java index 04013e3..099f42d 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/network/dto/EventDTO.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/network/dto/EventDTO.java @@ -15,7 +15,7 @@ /** * created by Tom on 10.02.2017. */ -public class EventDTO { +public class EventDTO implements BaseNetworkEntity { private static final String EVENT_ID_KEY = "id"; private static final String NAME_KEY = "name"; @@ -115,6 +115,7 @@ public void setPhotoPath(String photoPath) { this.photoPath = photoPath; } + @Override public String getId() { return id; } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/network/dto/UserDTO.java b/AndroidClient/src/main/java/com/tom/meeter/context/network/dto/UserDTO.java index 01ab39c..b2f9d26 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/network/dto/UserDTO.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/network/dto/UserDTO.java @@ -10,7 +10,7 @@ import java.time.LocalDate; -public class UserDTO { +public class UserDTO implements BaseNetworkEntity { private static final String USER_ID_KEY = "id"; private static final String NAME_KEY = "name"; @@ -51,6 +51,7 @@ public static UserDTO encode(JSONObject json) { return result; } + @Override public String getId() { return id; } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/subscriber/Subscriber.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/subscriber/Subscriber.java index 11ccd3e..71c35d8 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/subscriber/Subscriber.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/subscriber/Subscriber.java @@ -1,8 +1,9 @@ package com.tom.meeter.context.profile.subscriber; +import com.tom.meeter.context.network.dto.BaseNetworkEntity; import com.tom.meeter.context.network.dto.UserDTO; -public class Subscriber { +public class Subscriber implements BaseNetworkEntity { private UserDTO user; private boolean amISubscribedTo; @@ -23,4 +24,9 @@ public boolean isAmISubscribedTo() { public void setAmISubscribedTo(boolean amISubscribedTo) { this.amISubscribedTo = amISubscribedTo; } + + @Override + public String getId() { + return user.getId(); + } } diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/BaseAdapter.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/BaseAdapter.java new file mode 100644 index 0000000..dc70557 --- /dev/null +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/BaseAdapter.java @@ -0,0 +1,72 @@ +package com.tom.meeter.infrastructure.components.adapter; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.DiffUtil; +import androidx.recyclerview.widget.RecyclerView; + +import com.tom.meeter.context.network.dto.BaseNetworkEntity; +import com.tom.meeter.infrastructure.components.binder.BaseViewHolderBinder; + +import java.util.ArrayList; +import java.util.List; + +public abstract class BaseAdapter + extends RecyclerView.Adapter { + + protected final BaseViewHolderBinder binder; + protected final List targets = new ArrayList<>(); + + protected BaseAdapter(BaseViewHolderBinder binder) { + this.binder = binder; + } + + public void setData(List newTargets) { + DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff( + new NetworkEntityDiffCallback<>(targets, newTargets)); + this.targets.clear(); + this.targets.addAll(newTargets); + diffResult.dispatchUpdatesTo(this); + } + + @Override + public void onBindViewHolder(@NonNull VH holder, int position) { + binder.bind(holder, targets.get(position)); + } + + @Override + public int getItemCount() { + return targets.size(); + } + + public static class NetworkEntityDiffCallback + extends DiffUtil.Callback { + + private final List oldTargets, newTargets; + + public NetworkEntityDiffCallback(List oldTargets, List newTargets) { + this.oldTargets = oldTargets; + this.newTargets = newTargets; + } + + @Override + public int getOldListSize() { + return oldTargets.size(); + } + + @Override + public int getNewListSize() { + return newTargets.size(); + } + + @Override + public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { + return oldTargets.get(oldItemPosition).equals(newTargets.get(newItemPosition)); + } + + @Override + public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { + return oldTargets.get(oldItemPosition).getId() + .equals(newTargets.get(newItemPosition).getId()); + } + } +} diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/BaseEventAdapter.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/BaseEventAdapter.java index fd8fe7c..c079f84 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/BaseEventAdapter.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/BaseEventAdapter.java @@ -1,72 +1,14 @@ package com.tom.meeter.infrastructure.components.adapter; -import androidx.annotation.NonNull; -import androidx.recyclerview.widget.DiffUtil; import androidx.recyclerview.widget.RecyclerView; import com.tom.meeter.context.network.dto.EventDTO; import com.tom.meeter.infrastructure.components.binder.EventBinder; -import java.util.ArrayList; -import java.util.List; - public abstract class BaseEventAdapter - extends RecyclerView.Adapter { - - private final EventBinder binder; - private final List events = new ArrayList<>(); - - protected BaseEventAdapter(EventBinder binder) { - this.binder = binder; - } - - public void setData(List newEvents) { - DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff( - new EventsDiffCallback(events, newEvents)); - this.events.clear(); - this.events.addAll(newEvents); - diffResult.dispatchUpdatesTo(this); - } - - @Override - public void onBindViewHolder(@NonNull T holder, int position) { - binder.bind(holder, events.get(position)); - } - - @Override - public int getItemCount() { - return events.size(); - } - - static class EventsDiffCallback extends DiffUtil.Callback { - - private final List oldEvents, newEvents; - - public EventsDiffCallback(List oldEvents, List newEvents) { - this.oldEvents = oldEvents; - this.newEvents = newEvents; - } - - @Override - public int getOldListSize() { - return oldEvents.size(); - } - - @Override - public int getNewListSize() { - return newEvents.size(); - } - - @Override - public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { - return oldEvents.get(oldItemPosition).getId() - .equals(newEvents.get(newItemPosition).getId()); - } + extends BaseAdapter { - @Override - public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { - return oldEvents.get(oldItemPosition) - .equals(newEvents.get(newItemPosition)); - } + public BaseEventAdapter(EventBinder binder) { + super(binder); } } diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/BaseSubscriberAdapter.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/BaseSubscriberAdapter.java index 01209aa..d40c981 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/BaseSubscriberAdapter.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/BaseSubscriberAdapter.java @@ -1,72 +1,14 @@ package com.tom.meeter.infrastructure.components.adapter; -import androidx.annotation.NonNull; -import androidx.recyclerview.widget.DiffUtil; import androidx.recyclerview.widget.RecyclerView; import com.tom.meeter.context.profile.subscriber.Subscriber; import com.tom.meeter.infrastructure.components.binder.SubscriberBinder; -import java.util.ArrayList; -import java.util.List; - public abstract class BaseSubscriberAdapter - extends RecyclerView.Adapter { - - protected final SubscriberBinder binder; - protected final List subs = new ArrayList<>(); - - protected BaseSubscriberAdapter(SubscriberBinder binder) { - this.binder = binder; - } - - public void setData(List newSubs) { - DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff( - new SubscriberDiffCallback(subs, newSubs)); - this.subs.clear(); - this.subs.addAll(newSubs); - diffResult.dispatchUpdatesTo(this); - } - - @Override - public void onBindViewHolder(@NonNull T holder, int position) { - binder.bind(holder, subs.get(position)); - } - - @Override - public int getItemCount() { - return subs.size(); - } - - static class SubscriberDiffCallback extends DiffUtil.Callback { - - private final List oldUsers, newUsers; - - public SubscriberDiffCallback(List oldUsers, List newUsers) { - this.oldUsers = oldUsers; - this.newUsers = newUsers; - } - - @Override - public int getOldListSize() { - return oldUsers.size(); - } - - @Override - public int getNewListSize() { - return newUsers.size(); - } - - @Override - public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { - return oldUsers.get(oldItemPosition).getUser().getId() - .equals(newUsers.get(newItemPosition).getUser().getId()); - } + extends BaseAdapter { - @Override - public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { - return oldUsers.get(oldItemPosition) - .equals(newUsers.get(newItemPosition)); - } + public BaseSubscriberAdapter(SubscriberBinder binder) { + super(binder); } } diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/BaseUserAdapter.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/BaseUserAdapter.java index 7b5c6eb..7d0e374 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/BaseUserAdapter.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/BaseUserAdapter.java @@ -1,72 +1,14 @@ package com.tom.meeter.infrastructure.components.adapter; -import androidx.annotation.NonNull; -import androidx.recyclerview.widget.DiffUtil; import androidx.recyclerview.widget.RecyclerView; import com.tom.meeter.context.network.dto.UserDTO; import com.tom.meeter.infrastructure.components.binder.UserBinder; -import java.util.ArrayList; -import java.util.List; - public abstract class BaseUserAdapter - extends RecyclerView.Adapter { - - private final UserBinder binder; - private final List users = new ArrayList<>(); - - protected BaseUserAdapter(UserBinder binder) { - this.binder = binder; - } - - public void setData(List newUsers) { - DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff( - new UsersDiffCallback(users, newUsers)); - this.users.clear(); - this.users.addAll(newUsers); - diffResult.dispatchUpdatesTo(this); - } - - @Override - public void onBindViewHolder(@NonNull T holder, int position) { - binder.bind(holder, users.get(position)); - } - - @Override - public int getItemCount() { - return users.size(); - } - - static class UsersDiffCallback extends DiffUtil.Callback { - - private final List oldUsers, newUsers; - - public UsersDiffCallback(List oldUsers, List newUsers) { - this.oldUsers = oldUsers; - this.newUsers = newUsers; - } - - @Override - public int getOldListSize() { - return oldUsers.size(); - } - - @Override - public int getNewListSize() { - return newUsers.size(); - } - - @Override - public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { - return oldUsers.get(oldItemPosition).getId() - .equals(newUsers.get(newItemPosition).getId()); - } + extends BaseAdapter { - @Override - public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { - return oldUsers.get(oldItemPosition) - .equals(newUsers.get(newItemPosition)); - } + public BaseUserAdapter(UserBinder binder) { + super(binder); } } From fcea199212cfc38e06a7737ca31bb49a1f48e675 Mon Sep 17 00:00:00 2001 From: Georgy Lebedik Date: Fri, 27 Jun 2025 00:32:43 +0300 Subject: [PATCH 16/32] Refactoring. --- .../profile}/adapter/BaseSubscriberAdapter.java | 3 ++- .../tom/meeter/context/profile/adapter/SubscribersAdapter.java | 1 - .../components => context/user}/adapter/BaseUserAdapter.java | 3 ++- .../java/com/tom/meeter/context/user/adapter/UsersAdapter.java | 1 - 4 files changed, 4 insertions(+), 4 deletions(-) rename AndroidClient/src/main/java/com/tom/meeter/{infrastructure/components => context/profile}/adapter/BaseSubscriberAdapter.java (77%) rename AndroidClient/src/main/java/com/tom/meeter/{infrastructure/components => context/user}/adapter/BaseUserAdapter.java (76%) diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/BaseSubscriberAdapter.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/adapter/BaseSubscriberAdapter.java similarity index 77% rename from AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/BaseSubscriberAdapter.java rename to AndroidClient/src/main/java/com/tom/meeter/context/profile/adapter/BaseSubscriberAdapter.java index d40c981..3c19d08 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/BaseSubscriberAdapter.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/adapter/BaseSubscriberAdapter.java @@ -1,8 +1,9 @@ -package com.tom.meeter.infrastructure.components.adapter; +package com.tom.meeter.context.profile.adapter; import androidx.recyclerview.widget.RecyclerView; import com.tom.meeter.context.profile.subscriber.Subscriber; +import com.tom.meeter.infrastructure.components.adapter.BaseAdapter; import com.tom.meeter.infrastructure.components.binder.SubscriberBinder; public abstract class BaseSubscriberAdapter diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/adapter/SubscribersAdapter.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/adapter/SubscribersAdapter.java index 89ebf33..0651a13 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/adapter/SubscribersAdapter.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/adapter/SubscribersAdapter.java @@ -14,7 +14,6 @@ import com.tom.meeter.context.profile.subscriber.Subscriber; import com.tom.meeter.context.user.service.UserService; import com.tom.meeter.databinding.ActivityProfileSubscriberItemBinding; -import com.tom.meeter.infrastructure.components.adapter.BaseSubscriberAdapter; import com.tom.meeter.infrastructure.components.binder.SubscriberBinder; import com.tom.meeter.infrastructure.components.viewholder.SubscriberViewHolder; import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/BaseUserAdapter.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/adapter/BaseUserAdapter.java similarity index 76% rename from AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/BaseUserAdapter.java rename to AndroidClient/src/main/java/com/tom/meeter/context/user/adapter/BaseUserAdapter.java index 7d0e374..a2a4eb9 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/BaseUserAdapter.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/adapter/BaseUserAdapter.java @@ -1,8 +1,9 @@ -package com.tom.meeter.infrastructure.components.adapter; +package com.tom.meeter.context.user.adapter; import androidx.recyclerview.widget.RecyclerView; import com.tom.meeter.context.network.dto.UserDTO; +import com.tom.meeter.infrastructure.components.adapter.BaseAdapter; import com.tom.meeter.infrastructure.components.binder.UserBinder; public abstract class BaseUserAdapter diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/adapter/UsersAdapter.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/adapter/UsersAdapter.java index b28129b..67660df 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/adapter/UsersAdapter.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/adapter/UsersAdapter.java @@ -8,7 +8,6 @@ import androidx.recyclerview.widget.RecyclerView; import com.tom.meeter.databinding.ActivityUserSubscriberItemBinding; -import com.tom.meeter.infrastructure.components.adapter.BaseUserAdapter; import com.tom.meeter.infrastructure.components.binder.UserBinder; import com.tom.meeter.infrastructure.components.viewholder.UserViewHolder; From b7983b13cda38ae29c34676a00511af507f5780b Mon Sep 17 00:00:00 2001 From: Georgy Lebedik Date: Fri, 27 Jun 2025 01:44:55 +0300 Subject: [PATCH 17/32] Refactoring. --- .../activity/EventLocationMapActivity.java | 102 ++++++++-------- .../event/activity/EventOnMapActivity.java | 112 +++++++++--------- .../event/activity/ProfileEventActivity.java | 6 +- .../event/viewmodel/EventViewModel.java | 4 +- .../meeter/context/image/ImageDownloader.java | 22 +--- ...BaseNetworkEntity.java => EntityBase.java} | 2 +- .../meeter/context/network/dto/EventDTO.java | 2 +- .../meeter/context/network/dto/UserDTO.java | 2 +- .../adapter/BaseSubscriberAdapter.java | 15 --- .../profile/adapter/SubscribersAdapter.java | 9 +- .../profile/fragment/GoogleMapsFragment.java | 6 +- .../profile/subscriber/Subscriber.java | 4 +- .../context/user/adapter/BaseUserAdapter.java | 15 --- .../context/user/adapter/GridViewAdapter.java | 5 +- .../context/user/adapter/UsersAdapter.java | 4 +- .../components/adapter/BaseAdapter.java | 19 +-- .../binder/PhotoDownloaderEventBinder.java | 4 +- .../PhotoDownloaderWithCacheEventBinder.java | 8 +- ...toDownloaderWithCacheSubscriberBinder.java | 6 +- 19 files changed, 155 insertions(+), 192 deletions(-) rename AndroidClient/src/main/java/com/tom/meeter/context/network/dto/{BaseNetworkEntity.java => EntityBase.java} (64%) delete mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/profile/adapter/BaseSubscriberAdapter.java delete mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/user/adapter/BaseUserAdapter.java diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventLocationMapActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventLocationMapActivity.java index 4f8fad3..b644820 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventLocationMapActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventLocationMapActivity.java @@ -1,7 +1,7 @@ package com.tom.meeter.context.event.activity; +import static com.tom.meeter.context.auth.infrastructure.AuthHelper.getAuthHeader; import static com.tom.meeter.context.profile.fragment.GoogleMapsFragment.ZOOM_VALUE; -import static com.tom.meeter.infrastructure.common.ImagesHelper.circleImage; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.showMessage; @@ -17,7 +17,6 @@ import android.widget.FrameLayout; import android.widget.Toast; -import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import com.google.android.gms.maps.CameraUpdateFactory; @@ -31,15 +30,14 @@ import com.google.android.gms.maps.model.MarkerOptions; import com.tom.meeter.App; import com.tom.meeter.R; -import com.tom.meeter.context.auth.infrastructure.AuthHelper; import com.tom.meeter.context.event.service.EventService; import com.tom.meeter.context.gps.domain.LocationTrackerListener; import com.tom.meeter.context.gps.service.LocationTrackerService; import com.tom.meeter.context.image.ImageDownloader; import com.tom.meeter.context.network.dto.EventDTO; import com.tom.meeter.databinding.ActivityEventPositionBinding; -import com.tom.meeter.infrastructure.common.Globals; -import com.tom.meeter.infrastructure.http.ErrorLogger; +import com.tom.meeter.infrastructure.common.ImagesHelper; +import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; import com.tom.meeter.infrastructure.http.HttpCodes; import javax.inject.Inject; @@ -69,6 +67,8 @@ public class EventLocationMapActivity extends AppCompatActivity private AccountManager accountManager; private LatLng userLocation; + private final Runnable onNotAuthenticated = this::finish; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -77,11 +77,13 @@ protected void onCreate(Bundle savedInstanceState) { if (extras == null) { showMessage(this, "Unable to show map without extras provided."); finish(); + return; } eventId = extras.getString(EventDispatcherActivity.EVENT_ID_KEY); if (eventId == null) { showMessage(this, "Unable to show map without event_id provided."); finish(); + return; } binding = ActivityEventPositionBinding.inflate(getLayoutInflater()); @@ -150,63 +152,53 @@ public void onMapReady(GoogleMap googleMap) { UiSettings uiSettings = gmap.getUiSettings(); uiSettings.setZoomControlsEnabled(true); - String token = AuthHelper.peekToken(accountManager); - String authHeader = Globals.getAuthHeader(token); - eventService.getEvent(authHeader, eventId).enqueue(new ErrorLogger<>(this) { - @Override - public void onResponse(Call call, Response response) { - if (response.code() == HttpCodes.OK) { - EventDTO event = response.body(); - - gmap.setOnMapClickListener( - latLng -> { - if (eventMarker != null) { - eventMarker.setPosition(latLng); - return; - } - if (userLocation != null) { - eventMarker = createEventMarker(latLng, event); - downloadEventImage(event); - } - Log.d(TAG, "Event marker is null, user location is null, nothing to do..."); - }); - - if (event.getLatitude() == null || event.getLongitude() == null) { - setupSingleLocationListener(); - return; - } - LatLng eventLatLng = new LatLng(event.getLatitude(), event.getLongitude()); - eventMarker = createEventMarker(eventLatLng, event); - gmap.moveCamera(CameraUpdateFactory.newLatLngZoom(eventLatLng, ZOOM_VALUE)); - downloadEventImage(event); - return; - } - if (response.code() == HttpCodes.NOT_AUTHENTICATED) { - EventLocationMapActivity.this.recreate(); - } - Log.i(TAG, "/event/{id}: " + response.code() + " : " + response.body()); - } - }); + eventService.getEvent(getAuthHeader(accountManager), eventId).enqueue( + new BaseOnNotAuthenticatedCallback<>(this, onNotAuthenticated) { + @Override + public void onResponse(Call call, Response resp) { + super.onResponse(call, resp); + if (resp.code() != HttpCodes.OK || resp.body() == null) { + return; + } + EventDTO event = resp.body(); + + gmap.setOnMapClickListener( + latLng -> { + if (eventMarker != null) { + eventMarker.setPosition(latLng); + return; + } + if (userLocation != null) { + setupEventMarker(latLng, event); + } + Log.d(TAG, "Event marker is null, user location" + + " is null, nothing to do..."); + }); + + if (event.getLatitude() == null || event.getLongitude() == null) { + setupSingleLocationListener(); + return; + } + LatLng latLng = new LatLng(event.getLatitude(), event.getLongitude()); + setupEventMarker(latLng, event); + gmap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, ZOOM_VALUE)); + } + }); } - @Nullable - private Marker createEventMarker(LatLng latLng, EventDTO event) { - return gmap.addMarker( + private void setupEventMarker(LatLng latLng, EventDTO event) { + eventMarker = gmap.addMarker( new MarkerOptions() .position(latLng) .title(event.getName())); - } - - private void downloadEventImage(EventDTO event) { - assert eventMarker != null; String photoPath = event.getPhotoPath(); - if (photoPath != null) { - imageDownloader.downloadEventImage( - photoPath, - EventLocationMapActivity.this.getApplicationContext(), - (photo) -> eventMarker.setIcon(BitmapDescriptorFactory.fromBitmap(circleImage(photo))), - EventLocationMapActivity.this::recreate); + if (photoPath == null) { + return; } + imageDownloader.downloadEventImage( + photoPath, this, ImagesHelper::circleImage, + (photo) -> eventMarker.setIcon(BitmapDescriptorFactory.fromBitmap(photo)), + onNotAuthenticated); } @Override diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventOnMapActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventOnMapActivity.java index a02ea0c..f409439 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventOnMapActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventOnMapActivity.java @@ -1,7 +1,7 @@ package com.tom.meeter.context.event.activity; +import static com.tom.meeter.context.auth.infrastructure.AuthHelper.getAuthHeader; import static com.tom.meeter.context.profile.fragment.GoogleMapsFragment.ZOOM_VALUE; -import static com.tom.meeter.infrastructure.common.ImagesHelper.circleImage; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.showMessage; @@ -9,7 +9,6 @@ import android.content.Context; import android.content.Intent; import android.os.Bundle; -import android.util.Log; import android.widget.FrameLayout; import androidx.appcompat.app.AppCompatActivity; @@ -19,18 +18,18 @@ import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.UiSettings; +import com.google.android.gms.maps.model.BitmapDescriptor; import com.google.android.gms.maps.model.BitmapDescriptorFactory; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.MarkerOptions; import com.tom.meeter.App; import com.tom.meeter.R; -import com.tom.meeter.context.auth.infrastructure.AuthHelper; import com.tom.meeter.context.event.service.EventService; import com.tom.meeter.context.image.ImageDownloader; import com.tom.meeter.context.network.dto.EventDTO; import com.tom.meeter.databinding.ActivityEventOnMapBinding; -import com.tom.meeter.infrastructure.common.Globals; -import com.tom.meeter.infrastructure.http.ErrorLogger; +import com.tom.meeter.infrastructure.common.ImagesHelper; +import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; import com.tom.meeter.infrastructure.http.HttpCodes; import javax.inject.Inject; @@ -42,14 +41,16 @@ public class EventOnMapActivity extends AppCompatActivity implements OnMapReadyCallback { private static final String TAG = EventOnMapActivity.class.getCanonicalName(); - private GoogleMap gmap; - private ActivityEventOnMapBinding binding; @Inject - EventService eventService; + EventService service; @Inject - ImageDownloader imageDownloader; + ImageDownloader imgDownloader; + //TODO remake onNotAuthenticated + private final Runnable onNotAuthenticated = this::finish; + private GoogleMap gmap; + private ActivityEventOnMapBinding binding; private AccountManager accountManager; private String eventId; @@ -61,11 +62,13 @@ protected void onCreate(Bundle savedInstanceState) { if (extras == null) { showMessage(this, "Unable to show map without extras provided."); finish(); + return; } eventId = extras.getString(EventDispatcherActivity.EVENT_ID_KEY); if (eventId == null) { showMessage(this, "Unable to show map without event_id provided."); finish(); + return; } binding = ActivityEventOnMapBinding.inflate(getLayoutInflater()); @@ -73,8 +76,8 @@ protected void onCreate(Bundle savedInstanceState) { setContentView(view); ((App) getApplication()).getEventComponent().inject(this); - accountManager = AccountManager.get(this); + accountManager = AccountManager.get(this); SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.eventOnMap); @@ -89,49 +92,52 @@ public void onMapReady(GoogleMap googleMap) { UiSettings uiSettings = gmap.getUiSettings(); uiSettings.setZoomControlsEnabled(true); - String token = AuthHelper.peekToken(accountManager); - String authHeader = Globals.getAuthHeader(token); - eventService.getEvent(authHeader, eventId).enqueue(new ErrorLogger<>(this) { - @Override - public void onResponse(Call call, Response response) { - if (response.code() == HttpCodes.OK) { - EventDTO event = response.body(); - Double latitude = event.getLatitude(); - Double longitude = event.getLongitude(); - if (latitude == null || longitude == null) { - showMessage(EventOnMapActivity.this, R.string.event_location_is_not_set_yet); - return; - } - LatLng eventLatLng = new LatLng(latitude, longitude); - String photoPath = event.getPhotoPath(); - if (photoPath == null) { - gmap.addMarker( - new MarkerOptions() - .position(eventLatLng) - .title(event.getName())); - gmap.moveCamera(CameraUpdateFactory.newLatLngZoom(eventLatLng, ZOOM_VALUE)); - } else { - imageDownloader.downloadEventImage( - photoPath, - EventOnMapActivity.this.getApplicationContext(), - (photo) -> { - gmap.addMarker( - new MarkerOptions() - .position(eventLatLng) - .icon(BitmapDescriptorFactory.fromBitmap(circleImage(photo))) - .title(event.getName())); - gmap.moveCamera(CameraUpdateFactory.newLatLngZoom(eventLatLng, ZOOM_VALUE)); - }, - EventOnMapActivity.this::recreate); - } - return; - } - if (response.code() == HttpCodes.NOT_AUTHENTICATED) { - EventOnMapActivity.this.recreate(); - } - Log.i(TAG, "/event/{id}: " + response.code() + " : " + response.body()); - } - }); + service.getEvent(getAuthHeader(accountManager), eventId).enqueue( + //TODO: + // token is not checked at start, + // in case of invalid token infinity recreation + new BaseOnNotAuthenticatedCallback<>(this, onNotAuthenticated) { + @Override + public void onResponse(Call call, Response resp) { + super.onResponse(call, resp); + if (resp.code() != HttpCodes.OK || resp.body() == null) { + return; + } + EventDTO event = resp.body(); + Double latitude = event.getLatitude(); + Double longitude = event.getLongitude(); + if (latitude == null || longitude == null) { + showMessage(EventOnMapActivity.this, R.string.event_location_is_not_set_yet); + return; + } + LatLng latLng = new LatLng(latitude, longitude); + String photoPath = event.getPhotoPath(); + if (photoPath == null) { + addMarkerMoveCamera(latLng, event.getName(), null); + return; + } + imgDownloader.downloadEventImage( + photoPath, EventOnMapActivity.this, + ImagesHelper::circleImage, + (photo) -> addMarkerMoveCamera( + latLng, + event.getName(), + BitmapDescriptorFactory.fromBitmap(photo)), + onNotAuthenticated); + return; + } + }); + } + + private void addMarkerMoveCamera( + LatLng latLng, String title, BitmapDescriptor bmd) { + gmap.addMarker( + new MarkerOptions() + .position(latLng) + .title(title) + .icon(bmd) + ); + gmap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, ZOOM_VALUE)); } @Override diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/ProfileEventActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/ProfileEventActivity.java index 5f6bdc0..742180e 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/ProfileEventActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/ProfileEventActivity.java @@ -203,9 +203,9 @@ public void onResponse(Call call, Response resp) { } void downloadAndUpdateLayoutPhoto(String photoPath) { - imgDownloader.downloadEventImage(photoPath, this, - this::updateLayoutPhoto, ImagesHelper::bigCircleImage, - this::recreate); + imgDownloader.downloadEventImage( + photoPath, this, ImagesHelper::bigCircleImage, + this::updateLayoutPhoto, this::recreate); } private void updateLayoutPhoto(Bitmap photo) { diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModel.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModel.java index 4f51ac5..8e13d41 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModel.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModel.java @@ -96,8 +96,8 @@ public void onResponse(Call call, Response resp) { return; } imageDownloader.downloadEventImage( - photoPath, ctx, eventPhoto::setValue, - ImagesHelper::bigCircleImage, onNotAuthenticated); + photoPath, ctx, ImagesHelper::bigCircleImage, + eventPhoto::setValue, onNotAuthenticated); } } ); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/image/ImageDownloader.java b/AndroidClient/src/main/java/com/tom/meeter/context/image/ImageDownloader.java index 7173553..f2b6b0f 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/image/ImageDownloader.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/image/ImageDownloader.java @@ -33,8 +33,8 @@ public ImageDownloader(ImageService imageService) { public void downloadEventImage( String photoPath, Context ctx, - Consumer onDownloaded, Function bodyConverter, + Consumer onDownloaded, Runnable onNotAuthenticated) { imageService.downloadEventImage(getAuthHeader(AccountManager.get(ctx)), photoPath) .enqueue(new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { @@ -53,26 +53,6 @@ public void onResponse(Call call, Response response) }); } - @Deprecated - public void downloadEventImage( - String photoPath, Context ctx, - Consumer onDownloaded, Runnable onNotAuthenticated) { - imageService.downloadEventImage(getAuthHeader(AccountManager.get(ctx)), photoPath) - .enqueue(new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { - @Override - public void onResponse(Call call, Response response) { - super.onResponse(call, response); - //Log.d(TAG, "/images/event" + photoPath + " downloaded..."); - if (response.code() == HttpCodes.OK) { - try (ResponseBody body = response.body()) { - onDownloaded.accept(body); - return; - } - } - } - }); - } - public void downloadUserImage( String photoPath, Context ctx, Function converter, diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/network/dto/BaseNetworkEntity.java b/AndroidClient/src/main/java/com/tom/meeter/context/network/dto/EntityBase.java similarity index 64% rename from AndroidClient/src/main/java/com/tom/meeter/context/network/dto/BaseNetworkEntity.java rename to AndroidClient/src/main/java/com/tom/meeter/context/network/dto/EntityBase.java index ee0c885..dfe8387 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/network/dto/BaseNetworkEntity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/network/dto/EntityBase.java @@ -1,5 +1,5 @@ package com.tom.meeter.context.network.dto; -public interface BaseNetworkEntity { +public interface EntityBase { String getId(); } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/network/dto/EventDTO.java b/AndroidClient/src/main/java/com/tom/meeter/context/network/dto/EventDTO.java index 099f42d..2365aaf 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/network/dto/EventDTO.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/network/dto/EventDTO.java @@ -15,7 +15,7 @@ /** * created by Tom on 10.02.2017. */ -public class EventDTO implements BaseNetworkEntity { +public class EventDTO implements EntityBase { private static final String EVENT_ID_KEY = "id"; private static final String NAME_KEY = "name"; diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/network/dto/UserDTO.java b/AndroidClient/src/main/java/com/tom/meeter/context/network/dto/UserDTO.java index b2f9d26..e889dbd 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/network/dto/UserDTO.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/network/dto/UserDTO.java @@ -10,7 +10,7 @@ import java.time.LocalDate; -public class UserDTO implements BaseNetworkEntity { +public class UserDTO implements EntityBase { private static final String USER_ID_KEY = "id"; private static final String NAME_KEY = "name"; diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/adapter/BaseSubscriberAdapter.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/adapter/BaseSubscriberAdapter.java deleted file mode 100644 index 3c19d08..0000000 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/adapter/BaseSubscriberAdapter.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.tom.meeter.context.profile.adapter; - -import androidx.recyclerview.widget.RecyclerView; - -import com.tom.meeter.context.profile.subscriber.Subscriber; -import com.tom.meeter.infrastructure.components.adapter.BaseAdapter; -import com.tom.meeter.infrastructure.components.binder.SubscriberBinder; - -public abstract class BaseSubscriberAdapter - extends BaseAdapter { - - public BaseSubscriberAdapter(SubscriberBinder binder) { - super(binder); - } -} diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/adapter/SubscribersAdapter.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/adapter/SubscribersAdapter.java index 0651a13..951ab03 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/adapter/SubscribersAdapter.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/adapter/SubscribersAdapter.java @@ -14,6 +14,7 @@ import com.tom.meeter.context.profile.subscriber.Subscriber; import com.tom.meeter.context.user.service.UserService; import com.tom.meeter.databinding.ActivityProfileSubscriberItemBinding; +import com.tom.meeter.infrastructure.components.adapter.BaseAdapter; import com.tom.meeter.infrastructure.components.binder.SubscriberBinder; import com.tom.meeter.infrastructure.components.viewholder.SubscriberViewHolder; import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; @@ -22,7 +23,8 @@ import retrofit2.Call; import retrofit2.Response; -public class SubscribersAdapter extends BaseSubscriberAdapter { +public class SubscribersAdapter + extends BaseAdapter { private static final String TAG = SubscribersAdapter.class.getCanonicalName(); @@ -34,9 +36,10 @@ public SubscribersAdapter( UserService service, Runnable onAuthFail, Context ctx, SubscriberBinder binder) { super(binder); - binder.setup( - this::onSubUnSubClick, user -> dispatchToUserActivity(ctx, user.getId())); logMethod(TAG, this); + binder.setup( + this::onSubUnSubClick, + user -> dispatchToUserActivity(ctx, user.getId())); this.service = service; this.onAuthFail = onAuthFail; this.ctx = ctx; diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/GoogleMapsFragment.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/GoogleMapsFragment.java index 7c8c4db..cd29265 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/GoogleMapsFragment.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/GoogleMapsFragment.java @@ -47,6 +47,7 @@ import com.tom.meeter.context.network.domain.SearchForEvents; import com.tom.meeter.context.network.dto.EventDTO; import com.tom.meeter.context.profile.domain.GMapEvent; +import com.tom.meeter.infrastructure.common.ImagesHelper; import com.tom.meeter.infrastructure.common.InfrastructureHelper; import com.tom.meeter.infrastructure.common.PreferencesHelper; import com.tom.meeter.infrastructure.eventbus.events.IncomeEvents; @@ -339,10 +340,11 @@ private void downloadPhotoForMarker(String photoPath, Marker marker) { return; } imageDownloader.downloadEventImage( - photoPath, getContext(), + photoPath, requireContext(), + ImagesHelper::circleImage, photo -> { if (photo != null) { - marker.setIcon(BitmapDescriptorFactory.fromBitmap(circleImage(photo))); + marker.setIcon(BitmapDescriptorFactory.fromBitmap(photo)); } }, () -> InfrastructureHelper.restartActivityFromFragment(this)); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/subscriber/Subscriber.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/subscriber/Subscriber.java index 71c35d8..7da101a 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/subscriber/Subscriber.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/subscriber/Subscriber.java @@ -1,9 +1,9 @@ package com.tom.meeter.context.profile.subscriber; -import com.tom.meeter.context.network.dto.BaseNetworkEntity; +import com.tom.meeter.context.network.dto.EntityBase; import com.tom.meeter.context.network.dto.UserDTO; -public class Subscriber implements BaseNetworkEntity { +public class Subscriber implements EntityBase { private UserDTO user; private boolean amISubscribedTo; diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/adapter/BaseUserAdapter.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/adapter/BaseUserAdapter.java deleted file mode 100644 index a2a4eb9..0000000 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/adapter/BaseUserAdapter.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.tom.meeter.context.user.adapter; - -import androidx.recyclerview.widget.RecyclerView; - -import com.tom.meeter.context.network.dto.UserDTO; -import com.tom.meeter.infrastructure.components.adapter.BaseAdapter; -import com.tom.meeter.infrastructure.components.binder.UserBinder; - -public abstract class BaseUserAdapter - extends BaseAdapter { - - public BaseUserAdapter(UserBinder binder) { - super(binder); - } -} diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/adapter/GridViewAdapter.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/adapter/GridViewAdapter.java index 3ef5748..657f567 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/adapter/GridViewAdapter.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/adapter/GridViewAdapter.java @@ -12,6 +12,7 @@ import com.tom.meeter.context.image.ImageDownloader; import com.tom.meeter.context.network.dto.EventDTO; import com.tom.meeter.databinding.CardItemBinding; +import com.tom.meeter.infrastructure.common.ImagesHelper; import java.util.List; @@ -51,8 +52,8 @@ public View getView(int position, View convertView, ViewGroup parent) { String photoPath = event.getPhotoPath(); if (photoPath != null) { imageDownloader.downloadEventImage( - photoPath, ctx, - (photo) -> holder.binding.imageView.setImageBitmap(circleImage(photo)), + photoPath, ctx, ImagesHelper::circleImage, + holder.binding.imageView::setImageBitmap, onAuthFail); } } else { diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/adapter/UsersAdapter.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/adapter/UsersAdapter.java index 67660df..2522760 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/adapter/UsersAdapter.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/adapter/UsersAdapter.java @@ -7,11 +7,13 @@ import androidx.recyclerview.widget.RecyclerView; +import com.tom.meeter.context.network.dto.UserDTO; import com.tom.meeter.databinding.ActivityUserSubscriberItemBinding; +import com.tom.meeter.infrastructure.components.adapter.BaseAdapter; import com.tom.meeter.infrastructure.components.binder.UserBinder; import com.tom.meeter.infrastructure.components.viewholder.UserViewHolder; -public class UsersAdapter extends BaseUserAdapter { +public class UsersAdapter extends BaseAdapter { private static final String TAG = UsersAdapter.class.getCanonicalName(); diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/BaseAdapter.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/BaseAdapter.java index dc70557..bac68cb 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/BaseAdapter.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/adapter/BaseAdapter.java @@ -4,13 +4,13 @@ import androidx.recyclerview.widget.DiffUtil; import androidx.recyclerview.widget.RecyclerView; -import com.tom.meeter.context.network.dto.BaseNetworkEntity; +import com.tom.meeter.context.network.dto.EntityBase; import com.tom.meeter.infrastructure.components.binder.BaseViewHolderBinder; import java.util.ArrayList; import java.util.List; -public abstract class BaseAdapter +public abstract class BaseAdapter extends RecyclerView.Adapter { protected final BaseViewHolderBinder binder; @@ -22,7 +22,7 @@ protected BaseAdapter(BaseViewHolderBinder binder) { public void setData(List newTargets) { DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff( - new NetworkEntityDiffCallback<>(targets, newTargets)); + new EntityBaseDiffCallback<>(targets, newTargets)); this.targets.clear(); this.targets.addAll(newTargets); diffResult.dispatchUpdatesTo(this); @@ -38,12 +38,12 @@ public int getItemCount() { return targets.size(); } - public static class NetworkEntityDiffCallback + public static class EntityBaseDiffCallback extends DiffUtil.Callback { private final List oldTargets, newTargets; - public NetworkEntityDiffCallback(List oldTargets, List newTargets) { + public EntityBaseDiffCallback(List oldTargets, List newTargets) { this.oldTargets = oldTargets; this.newTargets = newTargets; } @@ -59,12 +59,15 @@ public int getNewListSize() { } @Override - public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { - return oldTargets.get(oldItemPosition).equals(newTargets.get(newItemPosition)); + public boolean areContentsTheSame( + int oldItemPosition, int newItemPosition) { + return oldTargets.get(oldItemPosition) + .equals(newTargets.get(newItemPosition)); } @Override - public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { + public boolean areItemsTheSame( + int oldItemPosition, int newItemPosition) { return oldTargets.get(oldItemPosition).getId() .equals(newTargets.get(newItemPosition).getId()); } diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderEventBinder.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderEventBinder.java index 43ac1dc..d7fead6 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderEventBinder.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderEventBinder.java @@ -6,6 +6,7 @@ import com.tom.meeter.context.image.ImageDownloader; import com.tom.meeter.context.network.dto.EventDTO; +import com.tom.meeter.infrastructure.common.ImagesHelper; import com.tom.meeter.infrastructure.components.adapter.OnEventClickListener; import com.tom.meeter.infrastructure.components.viewholder.CardItemHolder; @@ -36,6 +37,7 @@ public void bind(CardItemHolder holder, EventDTO event) { return; } imageDownloader.downloadEventImage( - photoPath, ctx, (photo) -> holder.updatePhoto(circleImage(photo)), onAuthFail); + photoPath, ctx, ImagesHelper::circleImage, + holder::updatePhoto, onAuthFail); } } diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheEventBinder.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheEventBinder.java index d6f3b8a..0bdc9aa 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheEventBinder.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheEventBinder.java @@ -1,6 +1,5 @@ package com.tom.meeter.infrastructure.components.binder; -import static com.tom.meeter.infrastructure.common.ImagesHelper.circleImage; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; import android.content.Context; @@ -9,6 +8,7 @@ import com.tom.meeter.context.image.ImageDownloader; import com.tom.meeter.context.network.dto.EventDTO; +import com.tom.meeter.infrastructure.common.ImagesHelper; import com.tom.meeter.infrastructure.components.adapter.OnEventClickListener; import com.tom.meeter.infrastructure.components.viewholder.EventViewHolder; @@ -54,10 +54,10 @@ public void bind(EventViewHolder holder, EventDTO event) { } imageDownloader.downloadEventImage( photoPath, ctx, + ImagesHelper::circleImage, photo -> { - Bitmap circled = circleImage(photo); - holder.updatePhoto(circled); - imagesCache.put(photoPath, circled); + holder.updatePhoto(photo); + imagesCache.put(photoPath, photo); Log.d(TAG, "PhotoDownloaderWithCacheEventBinder: event " + "image downloaded for [" + photoPath + "], cache updated."); }, diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheSubscriberBinder.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheSubscriberBinder.java index ede0695..fb2a8fa 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheSubscriberBinder.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheSubscriberBinder.java @@ -87,9 +87,11 @@ private void sendUserClickEvent(UserDTO user) { } } - private void sendSubUnSubEvent(Subscriber sub, SubscriberViewHolder holder) { + private void sendSubUnSubEvent( + Subscriber sub, SubscriberViewHolder holder) { if (subUnSubClickListener != null) { - subUnSubClickListener.onSubUnSub(sub, holder.getBindingAdapterPosition()); + subUnSubClickListener.onSubUnSub( + sub, holder.getBindingAdapterPosition()); } } } From 985c06b83fcaa5b822b39d43c759ea4ba4f069fe Mon Sep 17 00:00:00 2001 From: Georgy Lebedik Date: Fri, 27 Jun 2025 02:29:21 +0300 Subject: [PATCH 18/32] Binders generalization. --- .../activity/EventLocationMapActivity.java | 3 +- .../profile/activity/SubscribersActivity.java | 5 +- .../activity/SubscriptionsActivity.java | 6 +- .../activity/UserSubscribersActivity.java | 13 +-- .../activity/UserSubscriptionsActivity.java | 9 +- .../context/user/adapter/UsersAdapter.java | 5 +- .../components/binder/BaseUserBinder.java | 11 +++ .../binder/PhotoDownloaderEventBinder.java | 2 - ...toDownloaderWithCacheSubscriberBinder.java | 97 ------------------- .../PhotoDownloaderWithCacheUserBinder.java | 65 ------------- .../binder/PhotoWithCacheDownloader.java | 48 +++++++++ .../binder/SubscriberBinderImpl.java | 62 ++++++++++++ .../components/binder/UserBinder.java | 7 +- .../components/binder/UserBinderImpl.java | 49 ++++++++++ .../src/main/res/values-en/strings.xml | 1 + .../src/main/res/values-ru-rRU/strings.xml | 1 + AndroidClient/src/main/res/values/strings.xml | 1 + 17 files changed, 194 insertions(+), 191 deletions(-) create mode 100644 AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/BaseUserBinder.java delete mode 100644 AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheSubscriberBinder.java delete mode 100644 AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheUserBinder.java create mode 100644 AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoWithCacheDownloader.java create mode 100644 AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/SubscriberBinderImpl.java create mode 100644 AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/UserBinderImpl.java diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventLocationMapActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventLocationMapActivity.java index b644820..0f4c373 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventLocationMapActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/EventLocationMapActivity.java @@ -107,7 +107,8 @@ protected void onCreate(Bundle savedInstanceState) { setResult(RESULT_OK, resultIntent); finish(); } else { - Toast.makeText(this, "Выберите точку на карте", Toast.LENGTH_SHORT).show(); + Toast.makeText(this, R.string.select_point_on_the_map, Toast.LENGTH_SHORT) + .show(); } }); } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscribersActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscribersActivity.java index 3dd7bab..4e1650a 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscribersActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscribersActivity.java @@ -2,7 +2,6 @@ import static com.tom.meeter.context.auth.infrastructure.AuthHelper.checkToken; import static com.tom.meeter.context.auth.infrastructure.AuthHelper.getAuthHeader; -import static com.tom.meeter.context.user.activity.UserActivity.dispatchToUserActivity; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; import android.accounts.AccountManager; @@ -21,7 +20,7 @@ import com.tom.meeter.context.token.service.TokenService; import com.tom.meeter.context.user.service.UserService; import com.tom.meeter.databinding.ActivityProfileSubscribersBinding; -import com.tom.meeter.infrastructure.components.binder.PhotoDownloaderWithCacheSubscriberBinder; +import com.tom.meeter.infrastructure.components.binder.SubscriberBinderImpl; import javax.inject.Inject; @@ -68,7 +67,7 @@ private void onInit(String token) { String auth = getAuthHeader(accountManager); adapter = new SubscribersAdapter( service, onAuthFail, this, - new PhotoDownloaderWithCacheSubscriberBinder( + new SubscriberBinderImpl( this, imgDownloader, onAuthFail)); binding.recyclerSubscribers.setLayoutManager(new LinearLayoutManager(this)); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscriptionsActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscriptionsActivity.java index f44310a..0058def 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscriptionsActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscriptionsActivity.java @@ -2,7 +2,6 @@ import static com.tom.meeter.context.auth.infrastructure.AuthHelper.checkToken; import static com.tom.meeter.context.auth.infrastructure.AuthHelper.getAuthHeader; -import static com.tom.meeter.context.user.activity.UserActivity.dispatchToUserActivity; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; import android.accounts.AccountManager; @@ -21,7 +20,7 @@ import com.tom.meeter.context.token.service.TokenService; import com.tom.meeter.context.user.service.UserService; import com.tom.meeter.databinding.ActivityProfileSubscriptionsBinding; -import com.tom.meeter.infrastructure.components.binder.PhotoDownloaderWithCacheSubscriberBinder; +import com.tom.meeter.infrastructure.components.binder.SubscriberBinderImpl; import javax.inject.Inject; @@ -69,8 +68,7 @@ private void onInit(String token) { adapter = new SubscribersAdapter( userService, onAuthFail, this, - new PhotoDownloaderWithCacheSubscriberBinder( - this, imgDownloader, onAuthFail)); + new SubscriberBinderImpl(this, imgDownloader, onAuthFail)); binding.recyclerSubscriptions.setLayoutManager(new LinearLayoutManager(this)); binding.recyclerSubscriptions.setAdapter(adapter); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscribersActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscribersActivity.java index 44f89ae..aef04af 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscribersActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscribersActivity.java @@ -25,8 +25,7 @@ import com.tom.meeter.context.user.factory.UserSubscribersViewModelAssistedFactory; import com.tom.meeter.context.user.viewmodel.UserSubscribersViewModel; import com.tom.meeter.databinding.ActivityProfileSubscribersBinding; -import com.tom.meeter.infrastructure.common.Globals; -import com.tom.meeter.infrastructure.components.binder.PhotoDownloaderWithCacheUserBinder; +import com.tom.meeter.infrastructure.components.binder.UserBinderImpl; import javax.inject.Inject; @@ -41,6 +40,7 @@ public class UserSubscribersActivity extends AppCompatActivity { @Inject ImageDownloader imgDownloader; + private final Runnable onAuthFail = this::recreate; private AccountManager accountManager; private ActivityProfileSubscribersBinding binding; private UserSubscribersViewModel viewModel; @@ -69,11 +69,8 @@ protected void onCreate(Bundle savedInstanceState) { ((App) getApplication()).getUserComponent().inject(this); accountManager = AccountManager.get(this); - adapter = new UsersAdapter( - new PhotoDownloaderWithCacheUserBinder( - this, imgDownloader, - user -> dispatchToUserActivity(this, user.getId()), - this::recreate)); + adapter = new UsersAdapter(this, + new UserBinderImpl(this, imgDownloader, onAuthFail)); //setToken(accountManager, Launcher.EXPIRED); checkToken(this::onInit, this::finish, accountManager, this, tokenService); @@ -91,7 +88,7 @@ private void onInit(String token) { viewModel = new ViewModelProvider( this, assistedFactory.factory( - assistedFactory, userId, this, this::recreate)) + assistedFactory, userId, this, onAuthFail)) .get(UserSubscribersViewModel.class); viewModel.getSubscribers() diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscriptionsActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscriptionsActivity.java index 30a2521..fea2941 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscriptionsActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscriptionsActivity.java @@ -1,7 +1,6 @@ package com.tom.meeter.context.user.activity; import static com.tom.meeter.context.auth.infrastructure.AuthHelper.checkToken; -import static com.tom.meeter.context.user.activity.UserActivity.dispatchToUserActivity; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; import android.accounts.AccountManager; @@ -25,7 +24,7 @@ import com.tom.meeter.context.user.factory.UserSubscriptionsViewModelAssistedFactory; import com.tom.meeter.context.user.viewmodel.UserSubscriptionsViewModel; import com.tom.meeter.databinding.ActivityProfileSubscriptionsBinding; -import com.tom.meeter.infrastructure.components.binder.PhotoDownloaderWithCacheUserBinder; +import com.tom.meeter.infrastructure.components.binder.UserBinderImpl; import javax.inject.Inject; @@ -69,10 +68,8 @@ protected void onCreate(Bundle savedInstanceState) { accountManager = AccountManager.get(this); adapter = new UsersAdapter( - new PhotoDownloaderWithCacheUserBinder( - this, imgDownloader, - user -> dispatchToUserActivity(this, user.getId()), - this::recreate)); + this, + new UserBinderImpl(this, imgDownloader, this::recreate)); //setToken(accountManager, Launcher.EXPIRED); checkToken(this::onInit, this::finish, accountManager, this, tokenService); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/adapter/UsersAdapter.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/adapter/UsersAdapter.java index 2522760..1571901 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/adapter/UsersAdapter.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/adapter/UsersAdapter.java @@ -1,7 +1,9 @@ package com.tom.meeter.context.user.adapter; +import static com.tom.meeter.context.user.activity.UserActivity.dispatchToUserActivity; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; +import android.content.Context; import android.view.LayoutInflater; import android.view.ViewGroup; @@ -17,9 +19,10 @@ public class UsersAdapter extends BaseAdapter { private static final String TAG = UsersAdapter.class.getCanonicalName(); - public UsersAdapter(UserBinder binder) { + public UsersAdapter(Context ctx, UserBinder binder) { super(binder); logMethod(TAG, this); + binder.setup(user -> dispatchToUserActivity(ctx, user.getId())); } @Override diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/BaseUserBinder.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/BaseUserBinder.java new file mode 100644 index 0000000..f0d7e12 --- /dev/null +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/BaseUserBinder.java @@ -0,0 +1,11 @@ +package com.tom.meeter.infrastructure.components.binder; + +import androidx.recyclerview.widget.RecyclerView; + +import com.tom.meeter.context.network.dto.UserDTO; + +public interface BaseUserBinder + extends BaseViewHolderBinder { + + void bind(T holder, UserDTO target); +} diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderEventBinder.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderEventBinder.java index d7fead6..a510415 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderEventBinder.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderEventBinder.java @@ -1,7 +1,5 @@ package com.tom.meeter.infrastructure.components.binder; -import static com.tom.meeter.infrastructure.common.ImagesHelper.circleImage; - import android.content.Context; import com.tom.meeter.context.image.ImageDownloader; diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheSubscriberBinder.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheSubscriberBinder.java deleted file mode 100644 index fb2a8fa..0000000 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheSubscriberBinder.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.tom.meeter.infrastructure.components.binder; - -import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; - -import android.content.Context; -import android.graphics.Bitmap; -import android.util.Log; - -import com.tom.meeter.context.image.ImageDownloader; -import com.tom.meeter.context.network.dto.UserDTO; -import com.tom.meeter.context.profile.subscriber.Subscriber; -import com.tom.meeter.infrastructure.common.ImagesHelper; -import com.tom.meeter.infrastructure.components.adapter.OnSubscribeUnsubscribeClickListener; -import com.tom.meeter.infrastructure.components.adapter.OnUserClickListener; -import com.tom.meeter.infrastructure.components.viewholder.SubscriberViewHolder; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -public class PhotoDownloaderWithCacheSubscriberBinder - implements SubscriberBinder { - - private static final String TAG = PhotoDownloaderWithCacheSubscriberBinder.class.getCanonicalName(); - - private final Context ctx; - private final ImageDownloader imageDownloader; - private final Runnable onAuthFail; - private final Map imagesCache = new ConcurrentHashMap<>(); - - private OnUserClickListener userClickListener; - private OnSubscribeUnsubscribeClickListener subUnSubClickListener; - - public PhotoDownloaderWithCacheSubscriberBinder( - Context ctx, ImageDownloader imgDownloader, - Runnable onAuthFail) { - logMethod(TAG, this); - this.ctx = ctx; - this.imageDownloader = imgDownloader; - this.onAuthFail = onAuthFail; - } - - @Override - public void setup( - OnSubscribeUnsubscribeClickListener subUnSubClickListener, - OnUserClickListener userClickListener) { - this.subUnSubClickListener = subUnSubClickListener; - this.userClickListener = userClickListener; - } - - @Override - public void bind(SubscriberViewHolder holder, Subscriber target) { - UserDTO user = target.getUser(); - String photoPath = user.getPhotoPath(); - if (photoPath == null) { - holder.bind( - target.isAmISubscribedTo(), - user.getName(), user.getSurname(), null, - (v) -> sendUserClickEvent(user), - (v) -> sendSubUnSubEvent(target, holder) - ); - return; - } - Bitmap circledPhotoCache = imagesCache.get(photoPath); - holder.bind( - target.isAmISubscribedTo(), - user.getName(), user.getSurname(), circledPhotoCache, - (v) -> sendUserClickEvent(user), - (v) -> sendSubUnSubEvent(target, holder) - ); - if (circledPhotoCache != null) { - return; - } - imageDownloader.downloadUserImage( - photoPath, ctx, ImagesHelper::circleImage, - photo -> { - holder.updatePhoto(photo); - imagesCache.put(photoPath, photo); - Log.d(TAG, "PhotoDownloaderWithCacheUserBinder: user " + - "image downloaded for [" + photoPath + "], cache updated."); - }, - onAuthFail); - } - - private void sendUserClickEvent(UserDTO user) { - if (userClickListener != null) { - userClickListener.onClick(user); - } - } - - private void sendSubUnSubEvent( - Subscriber sub, SubscriberViewHolder holder) { - if (subUnSubClickListener != null) { - subUnSubClickListener.onSubUnSub( - sub, holder.getBindingAdapterPosition()); - } - } -} diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheUserBinder.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheUserBinder.java deleted file mode 100644 index 4206a1b..0000000 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheUserBinder.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.tom.meeter.infrastructure.components.binder; - -import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; - -import android.content.Context; -import android.graphics.Bitmap; -import android.util.Log; - -import com.tom.meeter.context.image.ImageDownloader; -import com.tom.meeter.context.network.dto.UserDTO; -import com.tom.meeter.infrastructure.common.ImagesHelper; -import com.tom.meeter.infrastructure.components.adapter.OnUserClickListener; -import com.tom.meeter.infrastructure.components.viewholder.UserViewHolder; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -public class PhotoDownloaderWithCacheUserBinder implements UserBinder { - - private static final String TAG = PhotoDownloaderWithCacheEventBinder.class.getCanonicalName(); - - private final Context ctx; - private final ImageDownloader imageDownloader; - private final OnUserClickListener userClickListener; - private final Runnable onAuthFail; - private final Map imagesCache = new ConcurrentHashMap<>(); - - public PhotoDownloaderWithCacheUserBinder( - Context ctx, ImageDownloader imgDownloader, - OnUserClickListener listener, - Runnable onAuthFail) { - logMethod(TAG, this); - this.ctx = ctx; - this.imageDownloader = imgDownloader; - this.userClickListener = listener; - this.onAuthFail = onAuthFail; - } - - @Override - public void bind(UserViewHolder holder, UserDTO user) { - String photoPath = user.getPhotoPath(); - if (photoPath == null) { - holder.bind( - user.getName(), user.getSurname(), null, - (v) -> userClickListener.onClick(user)); - return; - } - Bitmap circledPhotoCache = imagesCache.get(photoPath); - holder.bind( - user.getName(), user.getSurname(), circledPhotoCache, - (v) -> userClickListener.onClick(user)); - if (circledPhotoCache != null) { - return; - } - imageDownloader.downloadUserImage( - photoPath, ctx, ImagesHelper::circleImage, - photo -> { - holder.updatePhoto(photo); - imagesCache.put(photoPath, photo); - Log.d(TAG, "PhotoDownloaderWithCacheUserBinder: user " + - "image downloaded for [" + photoPath + "], cache updated."); - }, - onAuthFail); - } -} diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoWithCacheDownloader.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoWithCacheDownloader.java new file mode 100644 index 0000000..d13cb0a --- /dev/null +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoWithCacheDownloader.java @@ -0,0 +1,48 @@ +package com.tom.meeter.infrastructure.components.binder; + +import android.content.Context; +import android.graphics.Bitmap; +import android.util.Log; + +import com.tom.meeter.context.image.ImageDownloader; +import com.tom.meeter.infrastructure.common.ImagesHelper; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Consumer; + +public abstract class PhotoWithCacheDownloader { + + private static final String TAG = PhotoWithCacheDownloader.class.getCanonicalName(); + + protected final Context ctx; + protected final ImageDownloader imgDownloader; + protected final Runnable onAuthFail; + protected final Map cache = new ConcurrentHashMap<>(); + + protected PhotoWithCacheDownloader( + Context ctx, ImageDownloader imgDownloader, Runnable onAuthFail) { + this.ctx = ctx; + this.imgDownloader = imgDownloader; + this.onAuthFail = onAuthFail; + } + + protected void loadUserPhoto( + String photoPath, Consumer onImageReady) { + Bitmap cached = cache.get(photoPath); + if (cached != null) { + onImageReady.accept(cached); + return; + } + + imgDownloader.downloadUserImage( + photoPath, ctx, ImagesHelper::circleImage, + photo -> { + cache.put(photoPath, photo); + onImageReady.accept(photo); + Log.d(TAG, "PhotoWithCacheDownloader: user image downloaded for [" + + photoPath + "], cache updated."); + }, onAuthFail + ); + } +} \ No newline at end of file diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/SubscriberBinderImpl.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/SubscriberBinderImpl.java new file mode 100644 index 0000000..a8195e7 --- /dev/null +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/SubscriberBinderImpl.java @@ -0,0 +1,62 @@ +package com.tom.meeter.infrastructure.components.binder; + +import android.content.Context; +import android.graphics.Bitmap; + +import com.tom.meeter.context.image.ImageDownloader; +import com.tom.meeter.context.network.dto.UserDTO; +import com.tom.meeter.context.profile.subscriber.Subscriber; +import com.tom.meeter.infrastructure.components.adapter.OnSubscribeUnsubscribeClickListener; +import com.tom.meeter.infrastructure.components.adapter.OnUserClickListener; +import com.tom.meeter.infrastructure.components.viewholder.SubscriberViewHolder; + +public class SubscriberBinderImpl extends PhotoWithCacheDownloader + implements SubscriberBinder { + + private OnUserClickListener userClickListener; + private OnSubscribeUnsubscribeClickListener subUnSubClickListener; + + public SubscriberBinderImpl( + Context ctx, ImageDownloader imgDownloader, Runnable onAuthFail) { + super(ctx, imgDownloader, onAuthFail); + } + + @Override + public void setup( + OnSubscribeUnsubscribeClickListener subUnSubClickListener, + OnUserClickListener userClickListener) { + this.subUnSubClickListener = subUnSubClickListener; + this.userClickListener = userClickListener; + } + + @Override + public void bind(SubscriberViewHolder holder, Subscriber target) { + UserDTO user = target.getUser(); + String photoPath = user.getPhotoPath(); + + Bitmap cached = photoPath != null ? cache.get(photoPath) : null; + + holder.bind( + target.isAmISubscribedTo(), + user.getName(), user.getSurname(), cached, + v -> sendUserClickEvent(user), + v -> sendSubUnSubEvent(target, holder) + ); + + if (photoPath != null && cached == null) { + loadUserPhoto(photoPath, holder::updatePhoto); + } + } + + private void sendUserClickEvent(UserDTO user) { + if (userClickListener != null) { + userClickListener.onClick(user); + } + } + + private void sendSubUnSubEvent(Subscriber sub, SubscriberViewHolder holder) { + if (subUnSubClickListener != null) { + subUnSubClickListener.onSubUnSub(sub, holder.getBindingAdapterPosition()); + } + } +} diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/UserBinder.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/UserBinder.java index ed9d120..402ad6e 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/UserBinder.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/UserBinder.java @@ -2,10 +2,9 @@ import androidx.recyclerview.widget.RecyclerView; -import com.tom.meeter.context.network.dto.UserDTO; +import com.tom.meeter.infrastructure.components.adapter.OnUserClickListener; public interface UserBinder - extends BaseViewHolderBinder { - - void bind(T holder, UserDTO target); + extends BaseUserBinder { + void setup(OnUserClickListener userClickListener); } diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/UserBinderImpl.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/UserBinderImpl.java new file mode 100644 index 0000000..0bdd6d1 --- /dev/null +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/UserBinderImpl.java @@ -0,0 +1,49 @@ +package com.tom.meeter.infrastructure.components.binder; + +import android.content.Context; +import android.graphics.Bitmap; + +import com.tom.meeter.context.image.ImageDownloader; +import com.tom.meeter.context.network.dto.UserDTO; +import com.tom.meeter.infrastructure.components.adapter.OnUserClickListener; +import com.tom.meeter.infrastructure.components.viewholder.UserViewHolder; + +public class UserBinderImpl extends PhotoWithCacheDownloader + implements UserBinder { + + private OnUserClickListener userClickListener; + + public UserBinderImpl( + Context ctx, ImageDownloader imgDownloader, + Runnable onAuthFail) { + super(ctx, imgDownloader, onAuthFail); + } + + @Override + public void bind(UserViewHolder holder, UserDTO user) { + String photoPath = user.getPhotoPath(); + if (photoPath == null) { + holder.bind( + user.getName(), + user.getSurname(), + null, + v -> userClickListener.onClick(user)); + return; + } + + Bitmap cached = cache.get(photoPath); + holder.bind( + user.getName(), + user.getSurname(), + cached, v -> userClickListener.onClick(user)); + + if (cached == null) { + loadUserPhoto(photoPath, holder::updatePhoto); + } + } + + @Override + public void setup(OnUserClickListener userClickListener) { + this.userClickListener = userClickListener; + } +} diff --git a/AndroidClient/src/main/res/values-en/strings.xml b/AndroidClient/src/main/res/values-en/strings.xml index 2564e9c..6c97220 100644 --- a/AndroidClient/src/main/res/values-en/strings.xml +++ b/AndroidClient/src/main/res/values-en/strings.xml @@ -206,6 +206,7 @@ Show on map Select position Event location is not set yet. + Select point on the map 360p diff --git a/AndroidClient/src/main/res/values-ru-rRU/strings.xml b/AndroidClient/src/main/res/values-ru-rRU/strings.xml index cb5a7a6..7a1aafb 100644 --- a/AndroidClient/src/main/res/values-ru-rRU/strings.xml +++ b/AndroidClient/src/main/res/values-ru-rRU/strings.xml @@ -204,6 +204,7 @@ Показать на карте Выбор местоположения Местоположение события ещё не установлено. + Выберите точку на карте 360p diff --git a/AndroidClient/src/main/res/values/strings.xml b/AndroidClient/src/main/res/values/strings.xml index ac3959e..62b5d5b 100644 --- a/AndroidClient/src/main/res/values/strings.xml +++ b/AndroidClient/src/main/res/values/strings.xml @@ -204,6 +204,7 @@ Show on map Select position Event location is not set yet. + Select point on the map 360p From 49d13693897148d16ac16ecf0f9c0347bbc0d89e Mon Sep 17 00:00:00 2001 From: Georgy Lebedik Date: Fri, 27 Jun 2025 02:47:45 +0300 Subject: [PATCH 19/32] Binders generalization. --- .../fragment/ActiveEventsFragment.java | 6 +- .../fragment/ProfileEventsFragment.java | 6 +- .../profile/fragment/ProfileFragment.java | 4 +- .../context/user/activity/UserActivity.java | 4 +- .../PhotoWithCacheDownloader.java | 25 ++++--- .../components/UserImageDownloader.java | 26 ++++++++ .../components/binder/EventBinderImpl.java | 51 ++++++++++++++ .../PhotoDownloaderWithCacheEventBinder.java | 66 ------------------- ...Binder.java => SimpleEventBinderImpl.java} | 7 +- .../binder/SubscriberBinderImpl.java | 5 +- .../components/binder/UserBinderImpl.java | 26 +++----- 11 files changed, 113 insertions(+), 113 deletions(-) rename AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/{binder => }/PhotoWithCacheDownloader.java (61%) create mode 100644 AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/UserImageDownloader.java create mode 100644 AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/EventBinderImpl.java delete mode 100644 AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheEventBinder.java rename AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/{PhotoDownloaderEventBinder.java => SimpleEventBinderImpl.java} (85%) diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ActiveEventsFragment.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ActiveEventsFragment.java index 3a1e42a..716dcca 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ActiveEventsFragment.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ActiveEventsFragment.java @@ -24,7 +24,7 @@ import com.tom.meeter.context.profile.adapter.EventsAdapter; import com.tom.meeter.databinding.SubFragmentActiveEventsBinding; import com.tom.meeter.infrastructure.common.InfrastructureHelper; -import com.tom.meeter.infrastructure.components.binder.PhotoDownloaderWithCacheEventBinder; +import com.tom.meeter.infrastructure.components.binder.EventBinderImpl; import com.tom.meeter.infrastructure.eventbus.events.IncomeEvents; import org.greenrobot.eventbus.EventBus; @@ -57,9 +57,9 @@ public void onCreate(Bundle savedInstanceState) { EventBus.getDefault().register(this); - Context ctx = getContext(); + Context ctx = requireContext(); adapter = new EventsAdapter( - new PhotoDownloaderWithCacheEventBinder( + new EventBinderImpl( ctx, imageDownloader, (e) -> dispatchToEventActivity(ctx, e.getId()), () -> InfrastructureHelper.restartActivityFromFragment(this))); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileEventsFragment.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileEventsFragment.java index 35ed95f..d0a6df0 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileEventsFragment.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileEventsFragment.java @@ -24,7 +24,7 @@ import com.tom.meeter.context.profile.viewmodel.ProfileEventsViewModel; import com.tom.meeter.databinding.SubFragmentUserEventsBinding; import com.tom.meeter.infrastructure.common.InfrastructureHelper; -import com.tom.meeter.infrastructure.components.binder.PhotoDownloaderWithCacheEventBinder; +import com.tom.meeter.infrastructure.components.binder.EventBinderImpl; import javax.inject.Inject; @@ -56,11 +56,11 @@ public void onCreate(Bundle savedInstanceState) { ((App) getActivity().getApplication()).getComponent().inject(this); - Context ctx = getContext(); + Context ctx = requireContext(); accountManager = AccountManager.get(ctx); adapter = new EventsAdapter( - new PhotoDownloaderWithCacheEventBinder( + new EventBinderImpl( ctx, imageDownloader, (e) -> dispatchToEventActivity(ctx, e.getId()), () -> InfrastructureHelper.restartActivityFromFragment(this))); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileFragment.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileFragment.java index b3f76ea..2194fc5 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileFragment.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileFragment.java @@ -45,7 +45,7 @@ import com.tom.meeter.infrastructure.common.ImagesHelper; import com.tom.meeter.infrastructure.common.InfrastructureHelper; import com.tom.meeter.infrastructure.components.adapter.EventsCardAdapter; -import com.tom.meeter.infrastructure.components.binder.PhotoDownloaderEventBinder; +import com.tom.meeter.infrastructure.components.binder.SimpleEventBinderImpl; import com.tom.meeter.infrastructure.http.ActivityRestarterOnAuthFailure; import com.tom.meeter.infrastructure.http.HttpCodes; @@ -104,7 +104,7 @@ public void onCreate(Bundle savedInstanceState) { accountManager = AccountManager.get(ctx); adapter = new EventsCardAdapter( - new PhotoDownloaderEventBinder(ctx, imageDownloader, + new SimpleEventBinderImpl(ctx, imageDownloader, event -> dispatchToEventActivity(ctx, event.getId()), () -> InfrastructureHelper.restartActivityFromFragment(this))); } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java index 9a3ccf5..b186a3e 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java @@ -36,7 +36,7 @@ import com.tom.meeter.databinding.ActivityUserBinding; import com.tom.meeter.infrastructure.common.Globals; import com.tom.meeter.infrastructure.components.adapter.EventsCardAdapter; -import com.tom.meeter.infrastructure.components.binder.PhotoDownloaderEventBinder; +import com.tom.meeter.infrastructure.components.binder.SimpleEventBinderImpl; import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; import com.tom.meeter.infrastructure.http.HttpCodes; @@ -81,7 +81,7 @@ protected void onCreate(Bundle savedInstanceState) { ((App) getApplication()).getUserComponent().inject(this); adapter = new EventsCardAdapter( - new PhotoDownloaderEventBinder( + new SimpleEventBinderImpl( this, imgDownloader, event -> dispatchToEventActivity(this, event.getId()), this::recreate)); diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoWithCacheDownloader.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/PhotoWithCacheDownloader.java similarity index 61% rename from AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoWithCacheDownloader.java rename to AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/PhotoWithCacheDownloader.java index d13cb0a..69d225d 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoWithCacheDownloader.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/PhotoWithCacheDownloader.java @@ -1,11 +1,10 @@ -package com.tom.meeter.infrastructure.components.binder; +package com.tom.meeter.infrastructure.components; import android.content.Context; import android.graphics.Bitmap; import android.util.Log; import com.tom.meeter.context.image.ImageDownloader; -import com.tom.meeter.infrastructure.common.ImagesHelper; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -27,22 +26,20 @@ protected PhotoWithCacheDownloader( this.onAuthFail = onAuthFail; } - protected void loadUserPhoto( - String photoPath, Consumer onImageReady) { + protected void loadPhoto(String photoPath, Consumer onImageReady) { Bitmap cached = cache.get(photoPath); if (cached != null) { onImageReady.accept(cached); return; } - imgDownloader.downloadUserImage( - photoPath, ctx, ImagesHelper::circleImage, - photo -> { - cache.put(photoPath, photo); - onImageReady.accept(photo); - Log.d(TAG, "PhotoWithCacheDownloader: user image downloaded for [" - + photoPath + "], cache updated."); - }, onAuthFail - ); + downloadImage(photoPath, photo -> { + cache.put(photoPath, photo); + onImageReady.accept(photo); + Log.d(TAG, getClass().getSimpleName() + + ": image downloaded for [" + photoPath + "], cache updated."); + }); } -} \ No newline at end of file + + protected abstract void downloadImage(String photoPath, Consumer onDownloaded); +} diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/UserImageDownloader.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/UserImageDownloader.java new file mode 100644 index 0000000..157e60d --- /dev/null +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/UserImageDownloader.java @@ -0,0 +1,26 @@ +package com.tom.meeter.infrastructure.components; + +import android.content.Context; +import android.graphics.Bitmap; + +import com.tom.meeter.context.image.ImageDownloader; +import com.tom.meeter.infrastructure.common.ImagesHelper; + +import java.util.function.Consumer; + +public class UserImageDownloader extends PhotoWithCacheDownloader { + + protected UserImageDownloader( + Context ctx, ImageDownloader imgDownloader, Runnable onAuthFail) { + super(ctx, imgDownloader, onAuthFail); + } + + @Override + protected void downloadImage( + String photoPath, Consumer onDownloaded) { + imgDownloader.downloadUserImage( + photoPath, ctx, + ImagesHelper::circleImage, + onDownloaded, onAuthFail); + } +} diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/EventBinderImpl.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/EventBinderImpl.java new file mode 100644 index 0000000..1bac6b0 --- /dev/null +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/EventBinderImpl.java @@ -0,0 +1,51 @@ +package com.tom.meeter.infrastructure.components.binder; + +import android.content.Context; +import android.graphics.Bitmap; + +import com.tom.meeter.context.image.ImageDownloader; +import com.tom.meeter.context.network.dto.EventDTO; +import com.tom.meeter.infrastructure.common.ImagesHelper; +import com.tom.meeter.infrastructure.components.PhotoWithCacheDownloader; +import com.tom.meeter.infrastructure.components.adapter.OnEventClickListener; +import com.tom.meeter.infrastructure.components.viewholder.EventViewHolder; + +import java.util.function.Consumer; + +public class EventBinderImpl + extends PhotoWithCacheDownloader + implements EventBinder { + + private final OnEventClickListener listener; + + public EventBinderImpl( + Context ctx, ImageDownloader imgDownloader, + OnEventClickListener listener, Runnable onAuthFail) { + super(ctx, imgDownloader, onAuthFail); + this.listener = listener; + } + + @Override + public void bind(EventViewHolder holder, EventDTO event) { + String photoPath = event.getPhotoPath(); + + Bitmap cached = photoPath != null ? cache.get(photoPath) : null; + + holder.bind( + event.getName(), event.getDescription(), cached, + v -> listener.onClick(event)); + + if (photoPath != null && cached == null) { + loadPhoto(photoPath, holder::updatePhoto); + } + } + + @Override + protected void downloadImage(String photoPath, Consumer onDownloaded) { + imgDownloader.downloadEventImage( + photoPath, ctx, + ImagesHelper::circleImage, + onDownloaded, + onAuthFail); + } +} diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheEventBinder.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheEventBinder.java deleted file mode 100644 index 0bdc9aa..0000000 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderWithCacheEventBinder.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.tom.meeter.infrastructure.components.binder; - -import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; - -import android.content.Context; -import android.graphics.Bitmap; -import android.util.Log; - -import com.tom.meeter.context.image.ImageDownloader; -import com.tom.meeter.context.network.dto.EventDTO; -import com.tom.meeter.infrastructure.common.ImagesHelper; -import com.tom.meeter.infrastructure.components.adapter.OnEventClickListener; -import com.tom.meeter.infrastructure.components.viewholder.EventViewHolder; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -public class PhotoDownloaderWithCacheEventBinder - implements EventBinder { - - private static final String TAG = PhotoDownloaderWithCacheEventBinder.class.getCanonicalName(); - - private final Context ctx; - private final ImageDownloader imageDownloader; - private final OnEventClickListener listener; - private final Runnable onAuthFail; - private final Map imagesCache = new ConcurrentHashMap<>(); - - public PhotoDownloaderWithCacheEventBinder( - Context ctx, ImageDownloader imgDownloader, - OnEventClickListener listener, Runnable onAuthFail) { - logMethod(TAG, this); - this.ctx = ctx; - this.imageDownloader = imgDownloader; - this.listener = listener; - this.onAuthFail = onAuthFail; - } - - @Override - public void bind(EventViewHolder holder, EventDTO event) { - String photoPath = event.getPhotoPath(); - if (photoPath == null) { - holder.bind( - event.getName(), event.getDescription(), null, - (v) -> listener.onClick(event)); - return; - } - Bitmap circledPhotoCache = imagesCache.get(photoPath); - holder.bind( - event.getName(), event.getDescription(), circledPhotoCache, - (v) -> listener.onClick(event)); - if (circledPhotoCache != null) { - return; - } - imageDownloader.downloadEventImage( - photoPath, ctx, - ImagesHelper::circleImage, - photo -> { - holder.updatePhoto(photo); - imagesCache.put(photoPath, photo); - Log.d(TAG, "PhotoDownloaderWithCacheEventBinder: event " + - "image downloaded for [" + photoPath + "], cache updated."); - }, - onAuthFail); - } -} diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderEventBinder.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/SimpleEventBinderImpl.java similarity index 85% rename from AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderEventBinder.java rename to AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/SimpleEventBinderImpl.java index a510415..310af3d 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/PhotoDownloaderEventBinder.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/SimpleEventBinderImpl.java @@ -8,17 +8,16 @@ import com.tom.meeter.infrastructure.components.adapter.OnEventClickListener; import com.tom.meeter.infrastructure.components.viewholder.CardItemHolder; -public class PhotoDownloaderEventBinder - implements EventBinder { +public class SimpleEventBinderImpl implements EventBinder { - private static final String TAG = PhotoDownloaderEventBinder.class.getCanonicalName(); + private static final String TAG = SimpleEventBinderImpl.class.getCanonicalName(); private final Context ctx; private final ImageDownloader imageDownloader; private final OnEventClickListener listener; private final Runnable onAuthFail; - public PhotoDownloaderEventBinder( + public SimpleEventBinderImpl( Context ctx, ImageDownloader imageDownloader, OnEventClickListener listener, Runnable onAuthFail) { this.ctx = ctx; diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/SubscriberBinderImpl.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/SubscriberBinderImpl.java index a8195e7..48b55f1 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/SubscriberBinderImpl.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/SubscriberBinderImpl.java @@ -6,11 +6,12 @@ import com.tom.meeter.context.image.ImageDownloader; import com.tom.meeter.context.network.dto.UserDTO; import com.tom.meeter.context.profile.subscriber.Subscriber; +import com.tom.meeter.infrastructure.components.UserImageDownloader; import com.tom.meeter.infrastructure.components.adapter.OnSubscribeUnsubscribeClickListener; import com.tom.meeter.infrastructure.components.adapter.OnUserClickListener; import com.tom.meeter.infrastructure.components.viewholder.SubscriberViewHolder; -public class SubscriberBinderImpl extends PhotoWithCacheDownloader +public class SubscriberBinderImpl extends UserImageDownloader implements SubscriberBinder { private OnUserClickListener userClickListener; @@ -44,7 +45,7 @@ public void bind(SubscriberViewHolder holder, Subscriber target) { ); if (photoPath != null && cached == null) { - loadUserPhoto(photoPath, holder::updatePhoto); + loadPhoto(photoPath, holder::updatePhoto); } } diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/UserBinderImpl.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/UserBinderImpl.java index 0bdd6d1..59dca5c 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/UserBinderImpl.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/components/binder/UserBinderImpl.java @@ -5,40 +5,32 @@ import com.tom.meeter.context.image.ImageDownloader; import com.tom.meeter.context.network.dto.UserDTO; +import com.tom.meeter.infrastructure.components.UserImageDownloader; import com.tom.meeter.infrastructure.components.adapter.OnUserClickListener; import com.tom.meeter.infrastructure.components.viewholder.UserViewHolder; -public class UserBinderImpl extends PhotoWithCacheDownloader +public class UserBinderImpl extends UserImageDownloader implements UserBinder { private OnUserClickListener userClickListener; public UserBinderImpl( - Context ctx, ImageDownloader imgDownloader, - Runnable onAuthFail) { + Context ctx, ImageDownloader imgDownloader, Runnable onAuthFail) { super(ctx, imgDownloader, onAuthFail); } @Override public void bind(UserViewHolder holder, UserDTO user) { String photoPath = user.getPhotoPath(); - if (photoPath == null) { - holder.bind( - user.getName(), - user.getSurname(), - null, - v -> userClickListener.onClick(user)); - return; - } - Bitmap cached = cache.get(photoPath); + Bitmap cached = photoPath != null ? cache.get(photoPath) : null; + holder.bind( - user.getName(), - user.getSurname(), - cached, v -> userClickListener.onClick(user)); + user.getName(), user.getSurname(), cached, + v -> userClickListener.onClick(user)); - if (cached == null) { - loadUserPhoto(photoPath, holder::updatePhoto); + if (photoPath != null && cached == null) { + loadPhoto(photoPath, holder::updatePhoto); } } From 12b9102d6f2963e55d23b73b3579ec70fd923e4a Mon Sep 17 00:00:00 2001 From: Georgy Lebedik Date: Fri, 27 Jun 2025 03:06:09 +0300 Subject: [PATCH 20/32] Assisted factory types. --- .../context/user/factory/AssistedFactoryBase.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/AssistedFactoryBase.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/AssistedFactoryBase.java index eb3ff4b..64a229f 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/AssistedFactoryBase.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/AssistedFactoryBase.java @@ -9,15 +9,20 @@ public interface AssistedFactoryBase { T create(String userId, Context ctx, Runnable onNotAuthenticated); - default > ViewModelProvider.Factory factory( - F assistedFactory, String userId, Context ctx, + default ViewModelProvider.Factory factory( + AssistedFactoryBase assistedFactory, + String userId, Context ctx, Runnable onNotAuthenticated) { return new ViewModelProvider.Factory() { @Override @SuppressWarnings("unchecked") - //TODO associate T2 with T? - public T2 create(Class modelClass) { - return (T2) assistedFactory.create(userId, ctx, onNotAuthenticated); + public C create(Class modelClass) { + T result = assistedFactory.create(userId, ctx, onNotAuthenticated); + if (modelClass.isInstance(result)) { + return (C) result; + } + throw new IllegalArgumentException( + "Unknown ViewModel class: " + modelClass.getName()); } }; } From 7ba4fcc9b5f46a443b23efef58461d135e94aa46 Mon Sep 17 00:00:00 2001 From: Georgy Lebedik Date: Fri, 27 Jun 2025 03:47:13 +0300 Subject: [PATCH 21/32] Refactoring. --- .../event/activity/ProfileEventActivity.java | 27 +++++++------- .../event/activity/UserEventActivity.java | 13 +++---- .../event/factory/EventAssistedFactory.java | 11 ++++++ .../event/viewmodel/EventViewModel.java | 35 +++---------------- .../profile/activity/SubscribersActivity.java | 6 ++-- .../activity/SubscriptionsActivity.java | 13 +++---- .../profile/factory/AssistedFactoryBase.java | 17 +++++---- ...ctory.java => ProfileAssistedFactory.java} | 2 +- ...java => ProfileEventsAssistedFactory.java} | 2 +- ...=> ProfileSubscribersAssistedFactory.java} | 2 +- ... ProfileSubscriptionsAssistedFactory.java} | 2 +- .../fragment/ProfileEventsFragment.java | 12 ++----- .../profile/fragment/ProfileFragment.java | 9 +++-- .../viewmodel/ProfileEventsViewModel.java | 9 +++-- .../ProfileSubscribersViewModel.java | 9 +++-- .../ProfileSubscriptionsViewModel.java | 7 ++-- .../profile/viewmodel/ProfileViewModel.java | 18 +++++----- .../context/user/activity/UserActivity.java | 4 +-- .../activity/UserSubscribersActivity.java | 8 ++--- .../activity/UserSubscriptionsActivity.java | 4 +-- ...dFactory.java => UserAssistedFactory.java} | 5 +-- .../UserSubscribersAssistedFactory.java | 11 ++++++ ...erSubscribersViewModelAssistedFactory.java | 10 ------ .../UserSubscriptionsAssistedFactory.java | 11 ++++++ ...SubscriptionsViewModelAssistedFactory.java | 10 ------ .../factory/AssistedFactoryWithIdBase.java} | 18 +++++----- 26 files changed, 126 insertions(+), 149 deletions(-) create mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/event/factory/EventAssistedFactory.java rename AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/{ProfileViewModelAssistedFactory.java => ProfileAssistedFactory.java} (82%) rename AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/{ProfileEventsViewModelAssistedFactory.java => ProfileEventsAssistedFactory.java} (81%) rename AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/{ProfileSubscribersViewModelAssistedFactory.java => ProfileSubscribersAssistedFactory.java} (80%) rename AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/{ProfileSubscriptionsViewModelAssistedFactory.java => ProfileSubscriptionsAssistedFactory.java} (80%) rename AndroidClient/src/main/java/com/tom/meeter/context/user/factory/{UserViewModelAssistedFactory.java => UserAssistedFactory.java} (50%) create mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscribersAssistedFactory.java delete mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscribersViewModelAssistedFactory.java create mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscriptionsAssistedFactory.java delete mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscriptionsViewModelAssistedFactory.java rename AndroidClient/src/main/java/com/tom/meeter/{context/user/factory/AssistedFactoryBase.java => infrastructure/factory/AssistedFactoryWithIdBase.java} (51%) diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/ProfileEventActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/ProfileEventActivity.java index 742180e..6108165 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/ProfileEventActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/ProfileEventActivity.java @@ -35,6 +35,7 @@ import com.tom.meeter.App; import com.tom.meeter.R; +import com.tom.meeter.context.event.factory.EventAssistedFactory; import com.tom.meeter.context.event.message.UpdateEventRequest; import com.tom.meeter.context.event.service.EventService; import com.tom.meeter.context.event.viewmodel.EventViewModel; @@ -44,7 +45,6 @@ import com.tom.meeter.context.profile.activity.ProfileActivity; import com.tom.meeter.context.token.service.TokenService; import com.tom.meeter.databinding.ActivityEventEditableBinding; -import com.tom.meeter.infrastructure.common.Globals; import com.tom.meeter.infrastructure.common.ImagesHelper; import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; import com.tom.meeter.infrastructure.http.HttpCodes; @@ -67,12 +67,13 @@ public class ProfileEventActivity extends AppCompatActivity { @Inject TokenService tokenService; @Inject - EventService eventService; + EventService service; @Inject - EventViewModel.AssistedFactory assistedFactory; + EventAssistedFactory assistedFactory; @Inject ImageDownloader imgDownloader; + private final Runnable onNotAuthenticated = this::recreate; private ActivityEventEditableBinding binding; private AccountManager accountManager; private EventViewModel viewModel; @@ -129,18 +130,18 @@ protected void onCreate(Bundle savedInstanceState) { accountManager = AccountManager.get(this); //setToken(accountManager, Launcher.EXPIRED); - checkToken((token) -> onInit(token, eventId), this::finish, + checkToken((token) -> onInit(eventId), this::finish, accountManager, this, tokenService); } - private void onInit(String token, String eventId) { + private void onInit(String eventId) { viewModel = new ViewModelProvider( this, - EventViewModel.factory( - assistedFactory, eventId, token, this, this::recreate)) + assistedFactory.factory( + assistedFactory, eventId, this, onNotAuthenticated)) .get(EventViewModel.class); - initLayout(token); + initLayout(); viewModel.getEvent() .observe(this, event -> { @@ -156,7 +157,7 @@ private void onInit(String token, String eventId) { }); } - private void initLayout(String token) { + private void initLayout() { binding = ActivityEventEditableBinding.inflate(getLayoutInflater()); View view = binding.getRoot(); setContentView(view); @@ -178,8 +179,8 @@ private void initLayout(String token) { switchEditMode(); return; } - eventService.updateEvent(Globals.getAuthHeader(token), eventCache.getId(), req) - .enqueue(new BaseOnNotAuthenticatedCallback<>(this, this::recreate) { + service.updateEvent(getAuthHeader(accountManager), eventCache.getId(), req) + .enqueue(new BaseOnNotAuthenticatedCallback<>(this, onNotAuthenticated) { @Override public void onResponse(Call call, Response resp) { super.onResponse(call, resp); @@ -205,7 +206,7 @@ public void onResponse(Call call, Response resp) { void downloadAndUpdateLayoutPhoto(String photoPath) { imgDownloader.downloadEventImage( photoPath, this, ImagesHelper::bigCircleImage, - this::updateLayoutPhoto, this::recreate); + this::updateLayoutPhoto, onNotAuthenticated); } private void updateLayoutPhoto(Bitmap photo) { @@ -235,7 +236,7 @@ private void showAlertDialog() { .setTitle(R.string.delete_event) .setMessage(R.string.are_you_sure_delete_event) .setPositiveButton(R.string.delete, (dialog, which) -> { - eventService.deleteEvent(getAuthHeader(accountManager), eventCache.getId()) + service.deleteEvent(getAuthHeader(accountManager), eventCache.getId()) .enqueue(new HttpErrorLogger<>(getApplicationContext()) { @Override public void onResponse(Call call, Response resp) { diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/UserEventActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/UserEventActivity.java index 16889cd..e3c1158 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/UserEventActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/activity/UserEventActivity.java @@ -24,6 +24,7 @@ import androidx.lifecycle.ViewModelProvider; import com.tom.meeter.App; +import com.tom.meeter.context.event.factory.EventAssistedFactory; import com.tom.meeter.context.event.service.EventService; import com.tom.meeter.context.event.viewmodel.EventViewModel; import com.tom.meeter.context.network.dto.EventDTO; @@ -39,9 +40,9 @@ public class UserEventActivity extends AppCompatActivity { @Inject TokenService tokenService; @Inject - EventService eventService; + EventService service; @Inject - EventViewModel.AssistedFactory assistedFactory; + EventAssistedFactory assistedFactory; private ActivityEventReadableBinding binding; private EventViewModel viewModel; @@ -70,15 +71,15 @@ protected void onCreate(Bundle savedInstanceState) { accountManager = AccountManager.get(this); //setToken(accountManager, Launcher.EXPIRED); - checkToken((token) -> onInit(token, eventId), + checkToken((token) -> onInit(eventId), this::finish, accountManager, this, tokenService); } - private void onInit(String token, String eventId) { + private void onInit(String eventId) { viewModel = new ViewModelProvider( this, - EventViewModel.factory( - assistedFactory, eventId, token, this, this::recreate)) + assistedFactory.factory( + assistedFactory, eventId, this, this::recreate)) .get(EventViewModel.class); viewModel.getEvent() diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/factory/EventAssistedFactory.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/factory/EventAssistedFactory.java new file mode 100644 index 0000000..89a3d2c --- /dev/null +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/factory/EventAssistedFactory.java @@ -0,0 +1,11 @@ +package com.tom.meeter.context.event.factory; + +import com.tom.meeter.context.event.viewmodel.EventViewModel; +import com.tom.meeter.infrastructure.factory.AssistedFactoryWithIdBase; + +import dagger.assisted.AssistedFactory; + +@AssistedFactory +public interface EventAssistedFactory + extends AssistedFactoryWithIdBase { +} \ No newline at end of file diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModel.java b/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModel.java index 8e13d41..1df56dc 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModel.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/event/viewmodel/EventViewModel.java @@ -1,20 +1,20 @@ package com.tom.meeter.context.event.viewmodel; +import static com.tom.meeter.context.auth.infrastructure.AuthHelper.getAuthHeader; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; +import android.accounts.AccountManager; import android.content.Context; import android.graphics.Bitmap; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.ViewModel; -import androidx.lifecycle.ViewModelProvider; import com.tom.meeter.context.event.service.EventService; import com.tom.meeter.context.image.ImageDownloader; import com.tom.meeter.context.network.dto.EventDTO; import com.tom.meeter.context.user.viewmodel.UserViewModel; -import com.tom.meeter.infrastructure.common.Globals; import com.tom.meeter.infrastructure.common.ImagesHelper; import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; import com.tom.meeter.infrastructure.http.HttpCodes; @@ -27,13 +27,10 @@ public class EventViewModel extends ViewModel { private static final String TAG = UserViewModel.class.getCanonicalName(); - private static final String ASSISTED_EVENT = "event_id"; - private static final String ASSISTED_TOKEN = "token"; private final EventService eventService; private final ImageDownloader imageDownloader; private final String eventId; - private final String token; private final Context ctx; private final Runnable onNotAuthenticated; @@ -43,44 +40,20 @@ public class EventViewModel extends ViewModel { @AssistedInject public EventViewModel( EventService eventService, ImageDownloader imageDownloader, - @Assisted(ASSISTED_EVENT) String eventId, - @Assisted(ASSISTED_TOKEN) String token, + @Assisted String eventId, @Assisted Context ctx, @Assisted Runnable onNotAuthenticated) { logMethod(TAG, this); this.eventService = eventService; this.imageDownloader = imageDownloader; this.eventId = eventId; - this.token = token; this.ctx = ctx.getApplicationContext(); this.onNotAuthenticated = onNotAuthenticated; init(); } - @dagger.assisted.AssistedFactory - public interface AssistedFactory { - EventViewModel create( - @Assisted(ASSISTED_EVENT) String eventId, - @Assisted(ASSISTED_TOKEN) String token, - @Assisted Context ctx, - @Assisted Runnable onNotAuthenticated); - } - - public static ViewModelProvider.Factory factory( - AssistedFactory assistedFactory, - String eventId, String token, Context ctx, - Runnable onNotAuthenticated) { - return new ViewModelProvider.Factory() { - @Override - @SuppressWarnings("unchecked") - public T create(Class modelClass) { - return (T) assistedFactory.create(eventId, token, ctx, onNotAuthenticated); - } - }; - } - public void init() { - eventService.getEvent(Globals.getAuthHeader(token), eventId).enqueue( + eventService.getEvent(getAuthHeader(AccountManager.get(ctx)), eventId).enqueue( //TODO check toast... new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { @Override diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscribersActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscribersActivity.java index 4e1650a..a1b0035 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscribersActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscribersActivity.java @@ -15,7 +15,7 @@ import com.tom.meeter.App; import com.tom.meeter.context.image.ImageDownloader; import com.tom.meeter.context.profile.adapter.SubscribersAdapter; -import com.tom.meeter.context.profile.factory.ProfileSubscribersViewModelAssistedFactory; +import com.tom.meeter.context.profile.factory.ProfileSubscribersAssistedFactory; import com.tom.meeter.context.profile.viewmodel.ProfileSubscribersViewModel; import com.tom.meeter.context.token.service.TokenService; import com.tom.meeter.context.user.service.UserService; @@ -31,7 +31,7 @@ public class SubscribersActivity extends AppCompatActivity { @Inject TokenService tokenService; @Inject - ProfileSubscribersViewModelAssistedFactory assistedFactory; + ProfileSubscribersAssistedFactory assistedFactory; @Inject ImageDownloader imgDownloader; @Inject @@ -75,7 +75,7 @@ private void onInit(String token) { viewModel = new ViewModelProvider( this, - assistedFactory.factory(assistedFactory, auth, this, onAuthFail)) + assistedFactory.factory(assistedFactory, this, onAuthFail)) .get(ProfileSubscribersViewModel.class); viewModel.getSubscribers() diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscriptionsActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscriptionsActivity.java index 0058def..5e7e94d 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscriptionsActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/SubscriptionsActivity.java @@ -1,7 +1,6 @@ package com.tom.meeter.context.profile.activity; import static com.tom.meeter.context.auth.infrastructure.AuthHelper.checkToken; -import static com.tom.meeter.context.auth.infrastructure.AuthHelper.getAuthHeader; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; import android.accounts.AccountManager; @@ -15,7 +14,7 @@ import com.tom.meeter.App; import com.tom.meeter.context.image.ImageDownloader; import com.tom.meeter.context.profile.adapter.SubscribersAdapter; -import com.tom.meeter.context.profile.factory.ProfileSubscriptionsViewModelAssistedFactory; +import com.tom.meeter.context.profile.factory.ProfileSubscriptionsAssistedFactory; import com.tom.meeter.context.profile.viewmodel.ProfileSubscriptionsViewModel; import com.tom.meeter.context.token.service.TokenService; import com.tom.meeter.context.user.service.UserService; @@ -31,7 +30,7 @@ public class SubscriptionsActivity extends AppCompatActivity { @Inject TokenService tokenService; @Inject - ProfileSubscriptionsViewModelAssistedFactory assistedFactory; + ProfileSubscriptionsAssistedFactory assistedFactory; @Inject ImageDownloader imgDownloader; @Inject @@ -53,19 +52,17 @@ protected void onCreate(Bundle savedInstanceState) { accountManager = AccountManager.get(this); checkToken( - this::onInit, this::finish, + (token) -> onInit(), this::finish, accountManager, this, tokenService); } - private void onInit(String token) { + private void onInit() { logMethod(TAG, this); binding = ActivityProfileSubscriptionsBinding.inflate(getLayoutInflater()); View view = binding.getRoot(); setContentView(view); - String auth = getAuthHeader(accountManager); - adapter = new SubscribersAdapter( userService, onAuthFail, this, new SubscriberBinderImpl(this, imgDownloader, onAuthFail)); @@ -75,7 +72,7 @@ private void onInit(String token) { viewModel = new ViewModelProvider( this, - assistedFactory.factory(assistedFactory, auth, this, onAuthFail)) + assistedFactory.factory(assistedFactory, this, onAuthFail)) .get(ProfileSubscriptionsViewModel.class); viewModel.getSubscriptions() diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/AssistedFactoryBase.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/AssistedFactoryBase.java index 9fb2ad7..f42e4c7 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/AssistedFactoryBase.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/AssistedFactoryBase.java @@ -7,18 +7,21 @@ public interface AssistedFactoryBase { - T create(String auth, Context ctx, Runnable onNotAuthenticated); + T create(Context ctx, Runnable onNotAuthenticated); - default > ViewModelProvider.Factory factory( - F assistedFactory, - String auth, Context ctx, + default ViewModelProvider.Factory factory( + AssistedFactoryBase assistedFactory, Context ctx, Runnable onNotAuthenticated) { return new ViewModelProvider.Factory() { @Override @SuppressWarnings("unchecked") - //TODO associate T2 with T? - public T2 create(Class modelClass) { - return (T2) assistedFactory.create(auth, ctx, onNotAuthenticated); + public R create(Class modelClass) { + T result = assistedFactory.create(ctx, onNotAuthenticated); + if (modelClass.isInstance(result)) { + return (R) result; + } + throw new IllegalArgumentException( + "Unknown ViewModel class: " + modelClass.getName()); } }; } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileViewModelAssistedFactory.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileAssistedFactory.java similarity index 82% rename from AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileViewModelAssistedFactory.java rename to AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileAssistedFactory.java index 2cc078b..606bca3 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileViewModelAssistedFactory.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileAssistedFactory.java @@ -5,6 +5,6 @@ import dagger.assisted.AssistedFactory; @AssistedFactory -public interface ProfileViewModelAssistedFactory +public interface ProfileAssistedFactory extends AssistedFactoryBase { } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileEventsViewModelAssistedFactory.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileEventsAssistedFactory.java similarity index 81% rename from AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileEventsViewModelAssistedFactory.java rename to AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileEventsAssistedFactory.java index 338aa09..1c9eb78 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileEventsViewModelAssistedFactory.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileEventsAssistedFactory.java @@ -5,6 +5,6 @@ import dagger.assisted.AssistedFactory; @AssistedFactory -public interface ProfileEventsViewModelAssistedFactory +public interface ProfileEventsAssistedFactory extends AssistedFactoryBase { } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileSubscribersViewModelAssistedFactory.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileSubscribersAssistedFactory.java similarity index 80% rename from AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileSubscribersViewModelAssistedFactory.java rename to AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileSubscribersAssistedFactory.java index 7ce1963..3f94bd1 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileSubscribersViewModelAssistedFactory.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileSubscribersAssistedFactory.java @@ -5,6 +5,6 @@ import dagger.assisted.AssistedFactory; @AssistedFactory -public interface ProfileSubscribersViewModelAssistedFactory +public interface ProfileSubscribersAssistedFactory extends AssistedFactoryBase { } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileSubscriptionsViewModelAssistedFactory.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileSubscriptionsAssistedFactory.java similarity index 80% rename from AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileSubscriptionsViewModelAssistedFactory.java rename to AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileSubscriptionsAssistedFactory.java index c399b82..039e368 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileSubscriptionsViewModelAssistedFactory.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/factory/ProfileSubscriptionsAssistedFactory.java @@ -5,6 +5,6 @@ import dagger.assisted.AssistedFactory; @AssistedFactory -public interface ProfileSubscriptionsViewModelAssistedFactory +public interface ProfileSubscriptionsAssistedFactory extends AssistedFactoryBase { } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileEventsFragment.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileEventsFragment.java index d0a6df0..343e8e1 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileEventsFragment.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileEventsFragment.java @@ -1,10 +1,8 @@ package com.tom.meeter.context.profile.fragment; -import static com.tom.meeter.context.auth.infrastructure.AuthHelper.getAuthHeader; import static com.tom.meeter.context.event.activity.EventDispatcherActivity.dispatchToEventActivity; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; -import android.accounts.AccountManager; import android.content.Context; import android.os.Bundle; import android.view.LayoutInflater; @@ -20,7 +18,7 @@ import com.tom.meeter.App; import com.tom.meeter.context.image.ImageDownloader; import com.tom.meeter.context.profile.adapter.EventsAdapter; -import com.tom.meeter.context.profile.factory.ProfileEventsViewModelAssistedFactory; +import com.tom.meeter.context.profile.factory.ProfileEventsAssistedFactory; import com.tom.meeter.context.profile.viewmodel.ProfileEventsViewModel; import com.tom.meeter.databinding.SubFragmentUserEventsBinding; import com.tom.meeter.infrastructure.common.InfrastructureHelper; @@ -37,14 +35,12 @@ public class ProfileEventsFragment extends Fragment { private EventsAdapter adapter; @Inject - ProfileEventsViewModelAssistedFactory assistedFactory; + ProfileEventsAssistedFactory assistedFactory; @Inject ImageDownloader imageDownloader; private ProfileEventsViewModel viewModel; - private AccountManager accountManager; - public ProfileEventsFragment() { logMethod(TAG, this); } @@ -57,7 +53,6 @@ public void onCreate(Bundle savedInstanceState) { ((App) getActivity().getApplication()).getComponent().inject(this); Context ctx = requireContext(); - accountManager = AccountManager.get(ctx); adapter = new EventsAdapter( new EventBinderImpl( @@ -84,11 +79,10 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat super.onViewCreated(view, savedInstanceState); logMethod(TAG, this); - String auth = getAuthHeader(accountManager); viewModel = new ViewModelProvider( this, assistedFactory.factory( - assistedFactory, auth, requireContext(), + assistedFactory, requireContext(), () -> InfrastructureHelper.restartActivityFromFragment(this))) .get(ProfileEventsViewModel.class); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileFragment.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileFragment.java index 2194fc5..2d21d5b 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileFragment.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileFragment.java @@ -37,7 +37,7 @@ import com.tom.meeter.context.network.dto.UserDTO; import com.tom.meeter.context.profile.activity.SubscribersActivity; import com.tom.meeter.context.profile.activity.SubscriptionsActivity; -import com.tom.meeter.context.profile.factory.ProfileViewModelAssistedFactory; +import com.tom.meeter.context.profile.factory.ProfileAssistedFactory; import com.tom.meeter.context.profile.message.UpdateProfileRequest; import com.tom.meeter.context.profile.service.ProfileService; import com.tom.meeter.context.profile.viewmodel.ProfileViewModel; @@ -65,7 +65,7 @@ public class ProfileFragment extends Fragment { private static final String TAG = ProfileFragment.class.getCanonicalName(); @Inject - ProfileViewModelAssistedFactory assistedFactory; + ProfileAssistedFactory assistedFactory; @Inject ImageDownloader imageDownloader; @Inject @@ -122,11 +122,10 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat super.onViewCreated(view, savedInstanceState); logMethod(TAG, this); - String auth = getAuthHeader(accountManager); viewModel = new ViewModelProvider( this, assistedFactory.factory( - assistedFactory, auth, requireContext(), + assistedFactory, requireContext(), () -> InfrastructureHelper.restartActivityFromFragment(this))) .get(ProfileViewModel.class); @@ -155,7 +154,7 @@ assistedFactory, auth, requireContext(), switchEditMode(); return; } - profileService.updateProfile(auth, req) + profileService.updateProfile(getAuthHeader(accountManager), req) .enqueue(new ActivityRestarterOnAuthFailure<>(this) { @Override public void onResponse(Call call, Response response) { diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileEventsViewModel.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileEventsViewModel.java index c88a93c..f5160a5 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileEventsViewModel.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileEventsViewModel.java @@ -1,7 +1,9 @@ package com.tom.meeter.context.profile.viewmodel; +import static com.tom.meeter.context.auth.infrastructure.AuthHelper.getAuthHeader; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; +import android.accounts.AccountManager; import android.content.Context; import androidx.lifecycle.LiveData; @@ -24,29 +26,26 @@ public class ProfileEventsViewModel extends ViewModel { private static final String TAG = ProfileEventsViewModel.class.getCanonicalName(); - private final String auth; + private final ProfileService service; private final Context ctx; private final Runnable onNotAuthenticated; private final MutableLiveData> events = new MutableLiveData<>(); - private final ProfileService service; @AssistedInject public ProfileEventsViewModel( ProfileService service, - @Assisted String auth, @Assisted Context ctx, @Assisted Runnable onNotAuthenticated) { logMethod(TAG, this); this.service = service; - this.auth = auth; this.ctx = ctx.getApplicationContext(); this.onNotAuthenticated = onNotAuthenticated; init(); } public void init() { - service.getProfileEvents(auth).enqueue( + service.getProfileEvents(getAuthHeader(AccountManager.get(ctx))).enqueue( new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { @Override public void onResponse( diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileSubscribersViewModel.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileSubscribersViewModel.java index 016938b..e5bb19b 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileSubscribersViewModel.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileSubscribersViewModel.java @@ -1,7 +1,9 @@ package com.tom.meeter.context.profile.viewmodel; +import static com.tom.meeter.context.auth.infrastructure.AuthHelper.getAuthHeader; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; +import android.accounts.AccountManager; import android.content.Context; import androidx.lifecycle.LiveData; @@ -29,7 +31,6 @@ public class ProfileSubscribersViewModel extends ViewModel { private static final String TAG = ProfileSubscribersViewModel.class.getCanonicalName(); private final ProfileService service; - private final String auth; private final Context ctx; private final Runnable onNotAuthenticated; @@ -38,19 +39,17 @@ public class ProfileSubscribersViewModel extends ViewModel { @AssistedInject public ProfileSubscribersViewModel( ProfileService service, - @Assisted String auth, @Assisted Context ctx, @Assisted Runnable onNotAuthenticated) { logMethod(TAG, this); this.service = service; - this.auth = auth; this.ctx = ctx.getApplicationContext(); this.onNotAuthenticated = onNotAuthenticated; init(); } public void init() { - service.getMySubscriptions(auth).enqueue( + service.getMySubscriptions(getAuthHeader(AccountManager.get(ctx))).enqueue( new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { @Override public void onResponse( @@ -70,7 +69,7 @@ public void onResponse( } private void initSubscribers(Map mySubscriptions) { - service.getMySubscribers(auth).enqueue( + service.getMySubscribers(getAuthHeader(AccountManager.get(ctx))).enqueue( new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { @Override public void onResponse( diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileSubscriptionsViewModel.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileSubscriptionsViewModel.java index 957184a..53be0a8 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileSubscriptionsViewModel.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileSubscriptionsViewModel.java @@ -1,7 +1,9 @@ package com.tom.meeter.context.profile.viewmodel; +import static com.tom.meeter.context.auth.infrastructure.AuthHelper.getAuthHeader; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; +import android.accounts.AccountManager; import android.content.Context; import androidx.lifecycle.LiveData; @@ -27,7 +29,6 @@ public class ProfileSubscriptionsViewModel extends ViewModel { private static final String TAG = ProfileSubscribersViewModel.class.getCanonicalName(); private final ProfileService service; - private final String auth; private final Context ctx; private final Runnable onNotAuthenticated; @@ -36,19 +37,17 @@ public class ProfileSubscriptionsViewModel extends ViewModel { @AssistedInject public ProfileSubscriptionsViewModel( ProfileService service, - @Assisted String auth, @Assisted Context ctx, @Assisted Runnable onNotAuthenticated) { logMethod(TAG, this); this.service = service; - this.auth = auth; this.ctx = ctx.getApplicationContext(); this.onNotAuthenticated = onNotAuthenticated; init(); } public void init() { - service.getMySubscriptions(auth).enqueue( + service.getMySubscriptions(getAuthHeader(AccountManager.get(ctx))).enqueue( new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { @Override public void onResponse(Call> call, Response> resp) { diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileViewModel.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileViewModel.java index d3127d2..0b079d3 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileViewModel.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/viewmodel/ProfileViewModel.java @@ -1,7 +1,9 @@ package com.tom.meeter.context.profile.viewmodel; +import static com.tom.meeter.context.auth.infrastructure.AuthHelper.getAuthHeader; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; +import android.accounts.AccountManager; import android.content.Context; import android.graphics.Bitmap; @@ -28,34 +30,30 @@ public class ProfileViewModel extends ViewModel { private static final String TAG = ProfileViewModel.class.getCanonicalName(); - private final MutableLiveData profile = new MutableLiveData<>(); - private final MutableLiveData photo = new MutableLiveData<>(); - private final MutableLiveData> events = new MutableLiveData<>(); - private final ProfileService profileService; private final ImageDownloader imageDownloader; - - private final String auth; private final Context ctx; private final Runnable onNotAuthenticated; + private final MutableLiveData profile = new MutableLiveData<>(); + private final MutableLiveData photo = new MutableLiveData<>(); + private final MutableLiveData> events = new MutableLiveData<>(); + @AssistedInject public ProfileViewModel( ProfileService profileService, ImageDownloader imageDownloader, - @Assisted String auth, @Assisted Context ctx, @Assisted Runnable onNotAuthenticated) { logMethod(TAG, this); this.profileService = profileService; this.imageDownloader = imageDownloader; - this.auth = auth; this.ctx = ctx.getApplicationContext(); this.onNotAuthenticated = onNotAuthenticated; init(); } public void init() { - profileService.getProfile(auth).enqueue( + profileService.getProfile(getAuthHeader(AccountManager.get(ctx))).enqueue( new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { @Override public void onResponse(Call call, Response resp) { @@ -78,7 +76,7 @@ public void onResponse(Call call, Response resp) { } } ); - profileService.getProfileEvents(auth).enqueue( + profileService.getProfileEvents(getAuthHeader(AccountManager.get(ctx))).enqueue( new BaseOnNotAuthenticatedCallback<>(ctx, onNotAuthenticated) { @Override public void onResponse( diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java index b186a3e..dc77abd 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserActivity.java @@ -30,7 +30,7 @@ import com.tom.meeter.context.image.ImageDownloader; import com.tom.meeter.context.profile.activity.ProfileActivity; import com.tom.meeter.context.token.service.TokenService; -import com.tom.meeter.context.user.factory.UserViewModelAssistedFactory; +import com.tom.meeter.context.user.factory.UserAssistedFactory; import com.tom.meeter.context.user.service.UserService; import com.tom.meeter.context.user.viewmodel.UserViewModel; import com.tom.meeter.databinding.ActivityUserBinding; @@ -57,7 +57,7 @@ public class UserActivity extends AppCompatActivity { @Inject UserService userService; @Inject - UserViewModelAssistedFactory assistedFactory; + UserAssistedFactory assistedFactory; @Inject ImageDownloader imgDownloader; diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscribersActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscribersActivity.java index aef04af..2e62cfc 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscribersActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscribersActivity.java @@ -1,7 +1,6 @@ package com.tom.meeter.context.user.activity; import static com.tom.meeter.context.auth.infrastructure.AuthHelper.checkToken; -import static com.tom.meeter.context.user.activity.UserActivity.dispatchToUserActivity; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; import android.accounts.AccountManager; @@ -22,7 +21,7 @@ import com.tom.meeter.context.image.ImageDownloader; import com.tom.meeter.context.token.service.TokenService; import com.tom.meeter.context.user.adapter.UsersAdapter; -import com.tom.meeter.context.user.factory.UserSubscribersViewModelAssistedFactory; +import com.tom.meeter.context.user.factory.UserSubscribersAssistedFactory; import com.tom.meeter.context.user.viewmodel.UserSubscribersViewModel; import com.tom.meeter.databinding.ActivityProfileSubscribersBinding; import com.tom.meeter.infrastructure.components.binder.UserBinderImpl; @@ -36,7 +35,7 @@ public class UserSubscribersActivity extends AppCompatActivity { @Inject TokenService tokenService; @Inject - UserSubscribersViewModelAssistedFactory assistedFactory; + UserSubscribersAssistedFactory assistedFactory; @Inject ImageDownloader imgDownloader; @@ -69,7 +68,8 @@ protected void onCreate(Bundle savedInstanceState) { ((App) getApplication()).getUserComponent().inject(this); accountManager = AccountManager.get(this); - adapter = new UsersAdapter(this, + adapter = new UsersAdapter( + this, new UserBinderImpl(this, imgDownloader, onAuthFail)); //setToken(accountManager, Launcher.EXPIRED); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscriptionsActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscriptionsActivity.java index fea2941..4f52e43 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscriptionsActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/activity/UserSubscriptionsActivity.java @@ -21,7 +21,7 @@ import com.tom.meeter.context.image.ImageDownloader; import com.tom.meeter.context.token.service.TokenService; import com.tom.meeter.context.user.adapter.UsersAdapter; -import com.tom.meeter.context.user.factory.UserSubscriptionsViewModelAssistedFactory; +import com.tom.meeter.context.user.factory.UserSubscriptionsAssistedFactory; import com.tom.meeter.context.user.viewmodel.UserSubscriptionsViewModel; import com.tom.meeter.databinding.ActivityProfileSubscriptionsBinding; import com.tom.meeter.infrastructure.components.binder.UserBinderImpl; @@ -35,7 +35,7 @@ public class UserSubscriptionsActivity extends AppCompatActivity { @Inject TokenService tokenService; @Inject - UserSubscriptionsViewModelAssistedFactory assistedFactory; + UserSubscriptionsAssistedFactory assistedFactory; @Inject ImageDownloader imgDownloader; diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserViewModelAssistedFactory.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserAssistedFactory.java similarity index 50% rename from AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserViewModelAssistedFactory.java rename to AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserAssistedFactory.java index 98d83f1..c274082 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserViewModelAssistedFactory.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserAssistedFactory.java @@ -1,10 +1,11 @@ package com.tom.meeter.context.user.factory; import com.tom.meeter.context.user.viewmodel.UserViewModel; +import com.tom.meeter.infrastructure.factory.AssistedFactoryWithIdBase; import dagger.assisted.AssistedFactory; @AssistedFactory -public interface UserViewModelAssistedFactory - extends AssistedFactoryBase { +public interface UserAssistedFactory + extends AssistedFactoryWithIdBase { } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscribersAssistedFactory.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscribersAssistedFactory.java new file mode 100644 index 0000000..1097f06 --- /dev/null +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscribersAssistedFactory.java @@ -0,0 +1,11 @@ +package com.tom.meeter.context.user.factory; + +import com.tom.meeter.context.user.viewmodel.UserSubscribersViewModel; +import com.tom.meeter.infrastructure.factory.AssistedFactoryWithIdBase; + +import dagger.assisted.AssistedFactory; + +@AssistedFactory +public interface UserSubscribersAssistedFactory + extends AssistedFactoryWithIdBase { +} diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscribersViewModelAssistedFactory.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscribersViewModelAssistedFactory.java deleted file mode 100644 index bcbadd7..0000000 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscribersViewModelAssistedFactory.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.tom.meeter.context.user.factory; - -import com.tom.meeter.context.user.viewmodel.UserSubscribersViewModel; - -import dagger.assisted.AssistedFactory; - -@AssistedFactory -public interface UserSubscribersViewModelAssistedFactory - extends AssistedFactoryBase { -} diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscriptionsAssistedFactory.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscriptionsAssistedFactory.java new file mode 100644 index 0000000..3c146d2 --- /dev/null +++ b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscriptionsAssistedFactory.java @@ -0,0 +1,11 @@ +package com.tom.meeter.context.user.factory; + +import com.tom.meeter.context.user.viewmodel.UserSubscriptionsViewModel; +import com.tom.meeter.infrastructure.factory.AssistedFactoryWithIdBase; + +import dagger.assisted.AssistedFactory; + +@AssistedFactory +public interface UserSubscriptionsAssistedFactory + extends AssistedFactoryWithIdBase { +} diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscriptionsViewModelAssistedFactory.java b/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscriptionsViewModelAssistedFactory.java deleted file mode 100644 index c06c2ca..0000000 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/UserSubscriptionsViewModelAssistedFactory.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.tom.meeter.context.user.factory; - -import com.tom.meeter.context.user.viewmodel.UserSubscriptionsViewModel; - -import dagger.assisted.AssistedFactory; - -@AssistedFactory -public interface UserSubscriptionsViewModelAssistedFactory - extends AssistedFactoryBase { -} diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/AssistedFactoryBase.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/factory/AssistedFactoryWithIdBase.java similarity index 51% rename from AndroidClient/src/main/java/com/tom/meeter/context/user/factory/AssistedFactoryBase.java rename to AndroidClient/src/main/java/com/tom/meeter/infrastructure/factory/AssistedFactoryWithIdBase.java index 64a229f..30ea674 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/user/factory/AssistedFactoryBase.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/factory/AssistedFactoryWithIdBase.java @@ -1,25 +1,24 @@ -package com.tom.meeter.context.user.factory; +package com.tom.meeter.infrastructure.factory; import android.content.Context; import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModelProvider; -public interface AssistedFactoryBase { +public interface AssistedFactoryWithIdBase { - T create(String userId, Context ctx, Runnable onNotAuthenticated); + T create(String id, Context ctx, Runnable onNotAuthenticated); default ViewModelProvider.Factory factory( - AssistedFactoryBase assistedFactory, - String userId, Context ctx, - Runnable onNotAuthenticated) { + AssistedFactoryWithIdBase assistedFactory, + String id, Context ctx, Runnable onNotAuthenticated) { return new ViewModelProvider.Factory() { @Override @SuppressWarnings("unchecked") - public C create(Class modelClass) { - T result = assistedFactory.create(userId, ctx, onNotAuthenticated); + public R create(Class modelClass) { + T result = assistedFactory.create(id, ctx, onNotAuthenticated); if (modelClass.isInstance(result)) { - return (C) result; + return (R) result; } throw new IllegalArgumentException( "Unknown ViewModel class: " + modelClass.getName()); @@ -27,3 +26,4 @@ public C create(Class modelClass) { }; } } + From 4cb8ef206190826f157e2adca2a1c6f1a83bcb5d Mon Sep 17 00:00:00 2001 From: Georgy Lebedik Date: Fri, 27 Jun 2025 04:09:23 +0300 Subject: [PATCH 22/32] Refactoring. --- .../network/domain/CreateNewEventAttempt.java | 6 +- .../fragment/ActiveEventsFragment.java | 24 +++--- .../fragment/CreateNewEventFragment.java | 19 +++-- .../profile/fragment/ProfileFragment.java | 80 ++++++------------- .../meeter/context/profile/utils/Utils.java | 43 ++++++++++ .../infrastructure/common/DateHelper.java | 4 +- 6 files changed, 96 insertions(+), 80 deletions(-) create mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/profile/utils/Utils.java diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/network/domain/CreateNewEventAttempt.java b/AndroidClient/src/main/java/com/tom/meeter/context/network/domain/CreateNewEventAttempt.java index 3264daf..994117f 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/network/domain/CreateNewEventAttempt.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/network/domain/CreateNewEventAttempt.java @@ -11,12 +11,12 @@ public class CreateNewEventAttempt implements NetworkEvent { private final String description; private final OffsetDateTime starting; private final OffsetDateTime ending; - private final Float latitude; - private final Float longitude; + private final Double latitude; + private final Double longitude; public CreateNewEventAttempt( String name, String description, OffsetDateTime starting, - OffsetDateTime ending, Float latitude, Float longitude) { + OffsetDateTime ending, Double latitude, Double longitude) { this.name = name; this.description = description; this.starting = starting; diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ActiveEventsFragment.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ActiveEventsFragment.java index 716dcca..ff9f51f 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ActiveEventsFragment.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ActiveEventsFragment.java @@ -1,9 +1,5 @@ package com.tom.meeter.context.profile.fragment; -/** - * Created by Tom on 09.12.2016. - */ - import static com.tom.meeter.context.event.activity.EventDispatcherActivity.dispatchToEventActivity; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; @@ -33,15 +29,17 @@ import javax.inject.Inject; +/** + * Created by Tom on 09.12.2016. + */ public class ActiveEventsFragment extends Fragment { private static final String TAG = ActiveEventsFragment.class.getCanonicalName(); - SubFragmentActiveEventsBinding binding; - @Inject ImageDownloader imageDownloader; + private SubFragmentActiveEventsBinding binding; private EventsAdapter adapter; public ActiveEventsFragment() { @@ -69,17 +67,21 @@ public void onCreate(Bundle savedInstanceState) { @Override public View onCreateView( - @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + @NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { logMethod(TAG, this); - binding = SubFragmentActiveEventsBinding.inflate(inflater, container, false); + binding = SubFragmentActiveEventsBinding.inflate( + inflater, container, false); return binding.getRoot(); } @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + public void onViewCreated( + @NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); logMethod(TAG, this); - binding.activeEventsFragmentRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); + binding.activeEventsFragmentRecyclerView.setLayoutManager( + new LinearLayoutManager(getActivity())); binding.activeEventsFragmentRecyclerView.setAdapter(adapter); } @@ -95,4 +97,4 @@ public void onDestroy() { EventBus.getDefault().unregister(this); Log.d(TAG, "ActiveEventsFragment Unregistered event bus"); } -} \ No newline at end of file +} diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/CreateNewEventFragment.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/CreateNewEventFragment.java index ed7f8a7..2f175b0 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/CreateNewEventFragment.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/CreateNewEventFragment.java @@ -2,6 +2,7 @@ import static android.content.Context.BIND_AUTO_CREATE; import static com.tom.meeter.infrastructure.common.CommonHelper.EMPTY_STR; +import static com.tom.meeter.infrastructure.common.DateHelper.DATE_FORMAT; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; import android.annotation.SuppressLint; @@ -36,7 +37,6 @@ import org.greenrobot.eventbus.ThreadMode; import java.text.ParseException; -import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.LocalTime; import java.time.OffsetDateTime; @@ -51,7 +51,6 @@ public class CreateNewEventFragment extends Fragment { private static final String TAG = CreateNewEventFragment.class.getCanonicalName(); - private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); private static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern("HH:mm"); FragmentNewEventBinding binding; @@ -177,22 +176,22 @@ public void afterTextChanged(Editable s) { public void startsDateChangedListener() { String s = binding.newEventStartsDateEditText.getText().toString(); if (!isDateValid(s)) { - binding.newEventStartsDateTextView.setText(getString(R.string.wrong_date)); + binding.newEventStartsDateTextView.setText(R.string.wrong_date); binding.newEventCreateBtn.setEnabled(false); return; } - binding.newEventStartsDateTextView.setText(getString(R.string.correct_date)); + binding.newEventStartsDateTextView.setText(R.string.correct_date); validateWholeForm(); } public void endsDateChangedListener() { String e = binding.newEventEndsDateEditText.getText().toString(); if (!isDateValid(e)) { - binding.newEventEndsDateTextView.setText(getString(R.string.wrong_date)); + binding.newEventEndsDateTextView.setText(R.string.wrong_date); binding.newEventCreateBtn.setEnabled(false); return; } - binding.newEventEndsDateTextView.setText(getString(R.string.correct_date)); + binding.newEventEndsDateTextView.setText(R.string.correct_date); validateWholeForm(); } @@ -265,7 +264,7 @@ public void onDestroyView() { public void onDestroy() { super.onDestroy(); logMethod(TAG, this); - getContext().unbindService(locationServiceConnection); + requireContext().unbindService(locationServiceConnection); } @Override @@ -306,8 +305,8 @@ public void createEventClickHandler() { binding.newEventNameEditText.getText().toString(), binding.newEventDescriptionEditText.getText().toString(), starts, ends, - Float.valueOf(binding.newEventLatitudeEditText.getText().toString()), - Float.valueOf(binding.newEventLongitudeEditText.getText().toString()))); + Double.valueOf(binding.newEventLatitudeEditText.getText().toString()), + Double.valueOf(binding.newEventLongitudeEditText.getText().toString()))); } private static boolean requiredFieldsNotProvided( @@ -346,7 +345,7 @@ private static boolean isDateValid(String date) { @Subscribe(threadMode = ThreadMode.MAIN) public void onMessageEvent(SuccessfulEventCreation ev) { Log.d(TAG, ev.toString()); - new AlertDialog.Builder(getContext()) + new AlertDialog.Builder(requireContext()) .setTitle("Event created, id: " + ev.getId()) .setMessage("Created.") .setNegativeButton(getString(R.string.ok), (dialog, id) -> dialog.cancel()) diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileFragment.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileFragment.java index 2d21d5b..cdbfc03 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileFragment.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/ProfileFragment.java @@ -3,10 +3,9 @@ import static com.tom.meeter.context.auth.infrastructure.AuthHelper.getAuthHeader; import static com.tom.meeter.context.event.activity.EventDispatcherActivity.dispatchToEventActivity; import static com.tom.meeter.context.image.activity.BaseUploadActivity.PHOTO_PATH_RESULT; +import static com.tom.meeter.context.profile.utils.Utils.createUpdateProfileRequest; import static com.tom.meeter.infrastructure.common.CommonHelper.EMPTY_STR; import static com.tom.meeter.infrastructure.common.CommonHelper.genderResolver; -import static com.tom.meeter.infrastructure.common.CommonHelper.getLocalDateOrNull; -import static com.tom.meeter.infrastructure.common.CommonHelper.getStringOrNull; import static com.tom.meeter.infrastructure.common.DateHelper.getAgeFromDate; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.showMessage; @@ -46,7 +45,7 @@ import com.tom.meeter.infrastructure.common.InfrastructureHelper; import com.tom.meeter.infrastructure.components.adapter.EventsCardAdapter; import com.tom.meeter.infrastructure.components.binder.SimpleEventBinderImpl; -import com.tom.meeter.infrastructure.http.ActivityRestarterOnAuthFailure; +import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; import com.tom.meeter.infrastructure.http.HttpCodes; import java.time.LocalDate; @@ -71,6 +70,8 @@ public class ProfileFragment extends Fragment { @Inject ProfileService profileService; + private final Runnable onAuthFail = + () -> InfrastructureHelper.restartActivityFromFragment(this); private AccountManager accountManager; private EventsCardAdapter adapter; private FragmentProfileBinding binding; @@ -106,7 +107,7 @@ public void onCreate(Bundle savedInstanceState) { adapter = new EventsCardAdapter( new SimpleEventBinderImpl(ctx, imageDownloader, event -> dispatchToEventActivity(ctx, event.getId()), - () -> InfrastructureHelper.restartActivityFromFragment(this))); + onAuthFail)); } @Override @@ -122,11 +123,10 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat super.onViewCreated(view, savedInstanceState); logMethod(TAG, this); + Context ctx = requireContext(); viewModel = new ViewModelProvider( this, - assistedFactory.factory( - assistedFactory, requireContext(), - () -> InfrastructureHelper.restartActivityFromFragment(this))) + assistedFactory.factory(assistedFactory, ctx, onAuthFail)) .get(ProfileViewModel.class); LifecycleOwner owner = getViewLifecycleOwner(); @@ -148,25 +148,28 @@ assistedFactory, requireContext(), binding.btnEdit.setOnClickListener(v -> { if (isEditableModeEnabled) { - UpdateProfileRequest req = createUpdateProfileRequest(); + UpdateProfileRequest req = createUpdateProfileRequest(binding, userCache); if (req.isEmpty()) { showMessage(requireActivity(), R.string.empty_update_request_is_not_sent); switchEditMode(); return; } profileService.updateProfile(getAuthHeader(accountManager), req) - .enqueue(new ActivityRestarterOnAuthFailure<>(this) { + .enqueue(new BaseOnNotAuthenticatedCallback<>(ctx, onAuthFail) { @Override - public void onResponse(Call call, Response response) { + public void onResponse( + Call call, Response response) { super.onResponse(call, response); - if (response.code() == HttpCodes.OK) { - String oldPhotoPath = userCache.getPhotoPath(); - userCache = response.body(); - if (!Objects.equals(oldPhotoPath, userCache.getPhotoPath())) { - downloadAndUpdateLayoutPhoto(userCache.getPhotoPath()); - } - showMessage(ProfileFragment.this.requireActivity(), R.string.saved); + if (response.code() != HttpCodes.OK) { + updateLayoutValues(); + return; + } + String oldPhotoPath = userCache.getPhotoPath(); + userCache = response.body(); + if (!Objects.equals(oldPhotoPath, userCache.getPhotoPath())) { + downloadAndUpdateLayoutPhoto(userCache.getPhotoPath()); } + showMessage(requireActivity(), R.string.saved); updateLayoutValues(); } }); @@ -174,16 +177,11 @@ public void onResponse(Call call, Response response) { switchEditMode(); }); binding.subscribers.setOnClickListener( - v -> startActivity( - new Intent( - ProfileFragment.this.getContext(), SubscribersActivity.class))); + v -> startActivity(new Intent(ctx, SubscribersActivity.class))); binding.subscriptions.setOnClickListener( - v -> startActivity( - new Intent( - ProfileFragment.this.getContext(), SubscriptionsActivity.class))); + v -> startActivity(new Intent(ctx, SubscriptionsActivity.class))); binding.btnPhoto.setOnClickListener( - v -> imageUploadLauncher.launch( - new Intent(requireContext(), UploadUserImageActivity.class))); + v -> imageUploadLauncher.launch(new Intent(ctx, UploadUserImageActivity.class))); } private void updateLayoutValues() { @@ -199,9 +197,9 @@ private void updateLayoutValues() { } void downloadAndUpdateLayoutPhoto(String photoPath) { - imageDownloader.downloadUserImage(photoPath, requireContext(), - ImagesHelper::bigCircleImage, this::updateLayoutPhoto, - () -> InfrastructureHelper.restartActivityFromFragment(this)); + imageDownloader.downloadUserImage( + photoPath, requireContext(), ImagesHelper::bigCircleImage, + this::updateLayoutPhoto, onAuthFail); } private void updateLayoutPhoto(Bitmap photo) { @@ -219,32 +217,6 @@ private void switchEditMode() { isEditableModeEnabled ? getString(R.string.save) : getString(R.string.edit)); } - private UpdateProfileRequest createUpdateProfileRequest() { - UpdateProfileRequest req = new UpdateProfileRequest(); - - String nameChange = getStringOrNull(binding.name.getText()); - if (!Objects.equals(userCache.getName(), nameChange)) { - req.setName(nameChange); - } - String surnameChange = getStringOrNull(binding.surname.getText()); - if (!Objects.equals(userCache.getSurname(), surnameChange)) { - req.setSurname(surnameChange); - } - LocalDate birthdayChange = getLocalDateOrNull(binding.birthday.getText()); - if (!Objects.equals(userCache.getBirthday(), birthdayChange)) { - req.setBirthday(birthdayChange); - } - String infoChange = getStringOrNull(binding.info.getText()); - if (!Objects.equals(userCache.getInfo(), infoChange)) { - req.setInfo(infoChange); - } - String photoPathChange = getStringOrNull(binding.photoPath.getText()); - if (!Objects.equals(userCache.getPhotoPath(), photoPathChange)) { - req.setPhotoPath(photoPathChange); - } - return req; - } - @Override public void onPause() { super.onPause(); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/utils/Utils.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/utils/Utils.java new file mode 100644 index 0000000..6aa4403 --- /dev/null +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/utils/Utils.java @@ -0,0 +1,43 @@ +package com.tom.meeter.context.profile.utils; + +import static com.tom.meeter.infrastructure.common.CommonHelper.getLocalDateOrNull; +import static com.tom.meeter.infrastructure.common.CommonHelper.getStringOrNull; + +import com.tom.meeter.context.network.dto.UserDTO; +import com.tom.meeter.context.profile.message.UpdateProfileRequest; +import com.tom.meeter.databinding.FragmentProfileBinding; + +import java.time.LocalDate; +import java.util.Objects; + +public class Utils { + private Utils() { + } + + public static UpdateProfileRequest createUpdateProfileRequest( + FragmentProfileBinding binding, UserDTO user) { + UpdateProfileRequest req = new UpdateProfileRequest(); + + String nameChange = getStringOrNull(binding.name.getText()); + if (!Objects.equals(user.getName(), nameChange)) { + req.setName(nameChange); + } + String surnameChange = getStringOrNull(binding.surname.getText()); + if (!Objects.equals(user.getSurname(), surnameChange)) { + req.setSurname(surnameChange); + } + LocalDate birthdayChange = getLocalDateOrNull(binding.birthday.getText()); + if (!Objects.equals(user.getBirthday(), birthdayChange)) { + req.setBirthday(birthdayChange); + } + String infoChange = getStringOrNull(binding.info.getText()); + if (!Objects.equals(user.getInfo(), infoChange)) { + req.setInfo(infoChange); + } + String photoPathChange = getStringOrNull(binding.photoPath.getText()); + if (!Objects.equals(user.getPhotoPath(), photoPathChange)) { + req.setPhotoPath(photoPathChange); + } + return req; + } +} diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/common/DateHelper.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/common/DateHelper.java index 7a3f0a5..75a6032 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/common/DateHelper.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/common/DateHelper.java @@ -28,7 +28,7 @@ public final class DateHelper { private static final String TAG = DateHelper.class.getCanonicalName(); - private static final SimpleDateFormat FORMAT = new SimpleDateFormat("yyyy-MM-dd"); + public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); private DateHelper() { } @@ -42,7 +42,7 @@ public static String getAgeFromDateOld(String date) { Calendar today = Calendar.getInstance(); try { - dob.setTime(FORMAT.parse(date)); + dob.setTime(DATE_FORMAT.parse(date)); } catch (ParseException e) { Log.e(TAG, e.getLocalizedMessage(), e); return null; From b735b331db3b802ffc0fe38bc94a705973769c6e Mon Sep 17 00:00:00 2001 From: Georgy Lebedik Date: Sat, 28 Jun 2025 00:59:56 +0300 Subject: [PATCH 23/32] Fixed bug for profile activity rotation changes. --- AndroidClient/lint-baseline.xml | 52 ++-- .../auth/infrastructure/AuthHelper.java | 38 +-- .../profile/activity/ProfileActivity.java | 239 +++++++++++------- .../event/database/EventDatabase.java | 9 +- .../repository/event/domain/Event.java | 21 +- .../common/InfrastructureHelper.java | 12 + .../meeter/infrastructure/utils/Utils.java | 12 + .../src/main/res/layout/profile_activity.xml | 25 +- .../src/main/res/values-ru-rRU/strings.xml | 2 +- gradle/libs.versions.toml | 13 +- 10 files changed, 250 insertions(+), 173 deletions(-) create mode 100644 AndroidClient/src/main/java/com/tom/meeter/infrastructure/utils/Utils.java diff --git a/AndroidClient/lint-baseline.xml b/AndroidClient/lint-baseline.xml index e76a79a..3014b4b 100644 --- a/AndroidClient/lint-baseline.xml +++ b/AndroidClient/lint-baseline.xml @@ -4,23 +4,12 @@ - - - - + errorLine1=" public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + column="56"/> + + + + @@ -1349,7 +1349,7 @@ errorLine2=" ~~~~~~~~"> @@ -1360,7 +1360,7 @@ errorLine2=" ~~~~~~~~"> @@ -1371,7 +1371,7 @@ errorLine2=" ~~~~~~~~"> @@ -1481,7 +1481,7 @@ errorLine2=" ~~~~~~~~"> @@ -1492,7 +1492,7 @@ errorLine2=" ~~~~~~~~"> @@ -1503,7 +1503,7 @@ errorLine2=" ~~~~~~~~"> @@ -1811,7 +1811,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1822,7 +1822,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1833,7 +1833,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1910,7 +1910,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1921,7 +1921,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/auth/infrastructure/AuthHelper.java b/AndroidClient/src/main/java/com/tom/meeter/context/auth/infrastructure/AuthHelper.java index 624111f..20273a4 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/auth/infrastructure/AuthHelper.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/auth/infrastructure/AuthHelper.java @@ -71,26 +71,28 @@ public static void checkToken( AccountManager am, Activity activity, TokenService tokenService) { Account account = getSingleAccount(am); String token = am.peekAuthToken(account, AUTH_TYPE); - if (token == null) { - am.getAuthToken( - account, AUTH_TYPE, null, activity, - future -> { - Bundle result; - try { - result = future.getResult(); - } catch (AuthenticatorException e) { - throw new RuntimeException(e); - } catch (IOException e) { - throw new RuntimeException(e); - } catch (OperationCanceledException e) { - onCancelledAuth.run(); - return; - } - onToken.accept(result.getString(AccountManager.KEY_AUTHTOKEN)); - }, null); + if (token != null) { + checkTokenWithRetry( + tokenService, token, am, activity, + onToken, onCancelledAuth, 0); return; } - checkTokenWithRetry(tokenService, token, am, activity, onToken, onCancelledAuth, 0); + am.getAuthToken( + account, AUTH_TYPE, null, activity, + future -> { + Bundle result; + try { + result = future.getResult(); + } catch (AuthenticatorException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } catch (OperationCanceledException e) { + onCancelledAuth.run(); + return; + } + onToken.accept(result.getString(AccountManager.KEY_AUTHTOKEN)); + }, null); } private static void simpleCheckToken( diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/ProfileActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/ProfileActivity.java index 5be6eed..43dd142 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/ProfileActivity.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/ProfileActivity.java @@ -5,6 +5,7 @@ import static com.tom.meeter.context.auth.infrastructure.AuthHelper.getSingleAccount; import static com.tom.meeter.context.auth.infrastructure.AuthHelper.invalidateToken; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; +import static com.tom.meeter.infrastructure.utils.Utils.requireNonNull; import android.accounts.Account; import android.accounts.AccountManager; @@ -15,15 +16,14 @@ import android.content.SharedPreferences; import android.os.Build; import android.os.Bundle; -import android.os.Handler; import android.os.IBinder; -import android.os.Looper; import android.util.Log; import android.view.View; import android.view.inputmethod.InputMethodManager; import android.widget.ImageView; import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; @@ -50,6 +50,7 @@ import com.tom.meeter.App; import com.tom.meeter.R; import com.tom.meeter.context.auth.activity.LoginActivity; +import com.tom.meeter.context.auth.infrastructure.AuthHelper; import com.tom.meeter.context.network.service.SocketIOService; import com.tom.meeter.context.profile.fragment.CreateNewEventFragment; import com.tom.meeter.context.profile.fragment.EventsFragment; @@ -65,6 +66,7 @@ import com.tom.meeter.infrastructure.http.HttpCodes; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.function.Function; @@ -79,32 +81,35 @@ public class ProfileActivity extends AppCompatActivity { private static final String TAG = ProfileActivity.class.getCanonicalName(); private static final long DRAWER_PROFILE_ID = 0; + private static final String PROFILE_FRAGMENT_TAG = "profile_fragment_tag"; + private static final long DRAWER_EVENTS_ID = 1; + private static final String EVENTS_FRAGMENT_TAG = "events_fragment_tag"; + private static final long DRAWER_NEW_EVENT_ID = 2; + private static final String NEW_EVENT_FRAGMENT_TAG = "new_event_fragment_tag"; + private static final long DRAWER_NOTIFICATION_ID = 3; - private static final long DRAWER_SETTINGS_ID = 10; + private static final String NOTIFICATIONS_FRAGMENT_TAG = "notifications_fragment_tag"; + + private static final long DRAWER_SETTINGS_ID = 10; // -> no need a tag. + private static final long DRAWER_HELP_ID = 11; private static final long DRAWER_OPEN_SOURCE_ID = 12; private static final long DRAWER_CONTACT_ID = 13; private static final long DRAWER_LOGOUT_ID = 99; - private enum IconPackEnum { - FONT_AWESOME, - GOOGLE_MATERIALS - } - - private IconPackEnum icons = IconPackEnum.FONT_AWESOME; - private static final Map DRAWER_FRAGMENT_TAGS = new HashMap<>(); - private final Map drawerFragmentNames = new HashMap<>(); + static { - DRAWER_FRAGMENT_TAGS.put(DRAWER_PROFILE_ID, "profile_fragment_tag"); - DRAWER_FRAGMENT_TAGS.put(DRAWER_EVENTS_ID, "events_fragment_tag"); - DRAWER_FRAGMENT_TAGS.put(DRAWER_NEW_EVENT_ID, "new_event_fragment_tag"); - DRAWER_FRAGMENT_TAGS.put(DRAWER_NOTIFICATION_ID, "notifications_fragment_tag"); + DRAWER_FRAGMENT_TAGS.put(DRAWER_PROFILE_ID, PROFILE_FRAGMENT_TAG); + DRAWER_FRAGMENT_TAGS.put(DRAWER_EVENTS_ID, EVENTS_FRAGMENT_TAG); + DRAWER_FRAGMENT_TAGS.put(DRAWER_NEW_EVENT_ID, NEW_EVENT_FRAGMENT_TAG); + DRAWER_FRAGMENT_TAGS.put(DRAWER_NOTIFICATION_ID, NOTIFICATIONS_FRAGMENT_TAG); - //DRAWER_SETTINGS_ID intentionally don't need to have a tag, because it produces an activity + //DRAWER_SETTINGS_ID intentionally don't need to have a tag, + // because it produces an activity /* DRAWER_ITEMS.put(DRAWER_HELP_ID, null); @@ -113,15 +118,18 @@ private enum IconPackEnum { */ } - ProfileActivityBinding binding; + private enum IconPackEnum { + FONT_AWESOME, + GOOGLE_MATERIALS + } - private long lastNavItemId = 0; + private IconPackEnum icons = IconPackEnum.FONT_AWESOME; + private final Map drawerFragmentNames = new HashMap<>(); - private Drawer drawer = null; + private ProfileActivityBinding binding; // flag to load home fragment when user presses back key private boolean shouldLoadHomeFragOnBackPress = true; - private Handler replaceFragmentHandler; // urls to load navigation header background image // and profile image @@ -129,17 +137,22 @@ private enum IconPackEnum { private TextView txtName, txtWebsite; private FloatingActionButton fab; + @Inject SettingsService settingsService; @Inject ProfileService profileService; @Inject TokenService tokenService; + private ServiceConnection socketServiceConnection; private SocketIOService socketIOService; - private AccountManager accountManager; + private long lastNavItemId = DRAWER_PROFILE_ID; + + private Drawer drawer = null; + public ProfileActivity() { logMethod(TAG, this); } @@ -150,6 +163,10 @@ protected void onCreate(Bundle savedInstanceState) { logMethod(TAG, this); + binding = ProfileActivityBinding.inflate(getLayoutInflater()); + View view = binding.getRoot(); + setContentView(view); + ((App) getApplication()).getComponent().inject(this); accountManager = AccountManager.get(this); @@ -167,25 +184,23 @@ public void onServiceDisconnected(ComponentName name) { //setToken(accountManager, Launcher.EXPIRED); checkToken( - (token) -> onInit(token, savedInstanceState != null), + (token) -> onInit(savedInstanceState), this::finish, accountManager, this, tokenService); } - private void onInit(String token, boolean isSavedInstanceStateExist) { + private void onInit(Bundle savedInstanceState) { logMethod(TAG, this); - binding = ProfileActivityBinding.inflate(getLayoutInflater()); - View view = binding.getRoot(); - setContentView(view); - Log.d(TAG, "ProfileActivity binding SocketIOService"); - bindService(new Intent(this, SocketIOService.class), socketServiceConnection, BIND_AUTO_CREATE); - setupPreferences(token); + bindService( + new Intent(this, SocketIOService.class), + socketServiceConnection, BIND_AUTO_CREATE); + setupPreferences(); Toolbar toolbar = binding.profileActivityToolbar; setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); - replaceFragmentHandler = new Handler(Looper.getMainLooper()); + setupNameMapping( drawerFragmentNames, getResources().getStringArray(R.array.nav_item_activity_titles)); @@ -193,18 +208,21 @@ private void onInit(String token, boolean isSavedInstanceStateExist) { drawer.getAdapter() .withOnBindViewHolderListener(new OnBindViewHolderListenerImplBase()); - if (!isSavedInstanceStateExist) { + + if (savedInstanceState == null) { lastNavItemId = DRAWER_PROFILE_ID; renderSelectedFragment(); + } else { + restoreSettings(); } } - private void setupPreferences(String token) { - Call settings = settingsService.getSettings(Globals.getAuthHeader(token)); - settings.enqueue( + private void setupPreferences() { + settingsService.getSettings(AuthHelper.getAuthHeader(accountManager)).enqueue( new ErrorLogger<>(this) { @Override - public void onResponse(Call call, Response res) { + public void onResponse( + Call call, Response res) { if (res.code() == HttpCodes.NOT_AUTHENTICATED) { invalidateToken(accountManager, ProfileActivity.this, fresh -> setupPreferencesRetry(fresh), () -> finishAndRemoveTask()); @@ -226,7 +244,8 @@ private void setupPreferencesRetry(String freshToken) { settingsService.getSettings(Globals.getAuthHeader(freshToken)) .enqueue(new ErrorLogger<>(this) { @Override - public void onResponse(Call call, Response res) { + public void onResponse( + Call call, Response res) { if (res.code() == HttpCodes.NOT_FOUND) { // no settings on the server etc... return; @@ -255,14 +274,15 @@ public void onBackPressed() { // This code loads home fragment when back key is pressed // when user is in other fragment than home - if (shouldLoadHomeFragOnBackPress) { - if (lastNavItemId != DRAWER_PROFILE_ID) { - lastNavItemId = DRAWER_PROFILE_ID; - renderSelectedFragment(); - return; - } + if (!shouldLoadHomeFragOnBackPress) { + super.onBackPressed(); + return; + } + if (lastNavItemId != DRAWER_PROFILE_ID) { + lastNavItemId = DRAWER_PROFILE_ID; + renderSelectedFragment(); + return; } - super.onBackPressed(); } @@ -301,13 +321,14 @@ protected void onDestroy() { } private void unbindSocketService() { - if (socketIOService != null && socketServiceConnection != null) { - Log.d(TAG, "ProfileActivity unbinds SocketIOService via connection " - + socketServiceConnection); - unbindService(socketServiceConnection); - socketIOService = null; - socketServiceConnection = null; + if (socketIOService == null || socketServiceConnection == null) { + return; } + Log.d(TAG, "ProfileActivity unbinds SocketIOService via connection " + + socketServiceConnection); + unbindService(socketServiceConnection); + socketIOService = null; + socketServiceConnection = null; } private boolean onDrawerItemClickListener( @@ -315,11 +336,14 @@ private boolean onDrawerItemClickListener( long identifier = drawerItem.getIdentifier(); Log.d(TAG, "User selected drawer item: " + identifier + " previous was: " + lastNavItemId); - if (identifier == DRAWER_PROFILE_ID || identifier == DRAWER_EVENTS_ID - || identifier == DRAWER_NEW_EVENT_ID || identifier == DRAWER_NOTIFICATION_ID) { + if (identifier == DRAWER_PROFILE_ID + || identifier == DRAWER_EVENTS_ID + || identifier == DRAWER_NEW_EVENT_ID + || identifier == DRAWER_NOTIFICATION_ID) { lastNavItemId = identifier; } else if (identifier == DRAWER_LOGOUT_ID) { handleLogout(); + return true; } else if (identifier == DRAWER_SETTINGS_ID) { startActivity(new Intent(this, SettingsActivity.class)); drawer.setSelection(lastNavItemId, false); @@ -338,46 +362,28 @@ private boolean onDrawerItemClickListener( } private void renderSelectedFragment() { + logMethod(TAG, this); drawer.setSelection(lastNavItemId, false); - String tag = DRAWER_FRAGMENT_TAGS.get(lastNavItemId); - if (tag == null) { - throw new IllegalStateException("Fragment tag must be present"); - } + String tag = requireNonNull( + DRAWER_FRAGMENT_TAGS.get(lastNavItemId), + "Fragment tag must be present"); // if user select the current navigation menu again, don't do anything // just close the navigation drawer - FragmentManager supportFM = getSupportFragmentManager(); - if (supportFM.findFragmentByTag(tag) != null) { + FragmentManager fm = getSupportFragmentManager(); + if (fm.findFragmentByTag(tag) != null) { drawer.closeDrawer(); //toggleFab(); return; } // Since new navigation comes... - String title = drawerFragmentNames.get(lastNavItemId); - if (title == null) { - throw new IllegalStateException("Drawer toolbar title should be present"); - } - ActionBar actionBar = getSupportActionBar(); - if (actionBar == null) { - throw new IllegalStateException("ActionBar should be present"); + setupActionBarTitle(lastNavItemId); + + if (!fm.isStateSaved()) { + replaceFragment(fm, () -> createFragment(lastNavItemId), () -> tag) + .run(); } - actionBar.setTitle(title); - // Sometimes, when fragment has huge data, screen seems hanging - // when switching between navigation menus - // So using runnable, the fragment is loaded with cross fade effect - // This effect can be seen in GMail app - -/* binding.profileActivityFrame.removeAllViews(); - Fragment fragment = createFragment(lastNavItemId); - binding.profileActivityFrame.addView(fragment.getView());*/ - // If mPendingRunnable is not null, then add to the message queue - replaceFragmentHandler.post( - replaceFragment( - supportFM, - () -> createFragment(lastNavItemId), - () -> tag) - ); // show or hide the fab button //toggleFab(); @@ -388,6 +394,49 @@ private void renderSelectedFragment() { //invalidateOptionsMenu(); } + private void restoreSettings() { + logMethod(TAG, this); + Long fragmentId = getFragmentIdByTag( + getCurrentFragmentTag(getSupportFragmentManager())); + drawer.setSelection(fragmentId, false); + setupActionBarTitle(fragmentId); + drawer.closeDrawer(); + } + + private void setupActionBarTitle(Long fragmentId) { + String title = requireNonNull( + drawerFragmentNames.get(fragmentId), + "Drawer toolbar title should be present."); + ActionBar actionBar = requireNonNull( + getSupportActionBar(), + "ActionBar should be present."); + actionBar.setTitle(title); + } + + @NonNull + private static Long getFragmentIdByTag(String tag) { + for (Long id : DRAWER_FRAGMENT_TAGS.keySet()) { + if (tag.equals(DRAWER_FRAGMENT_TAGS.get(id))) { + return id; + } + } + throw new IllegalStateException("Fragment tag {" + tag + "} is not initialized."); + } + + @NonNull + private static String getCurrentFragmentTag(FragmentManager fm) { + List fragments = fm.getFragments(); + int size = fragments.size(); + if (size != 1) { + throw new IllegalStateException("Not exactly 1 fragments in manager, size {" + size + "}."); + } + String tag = fragments.get(0).getTag(); + if (tag == null) { + throw new IllegalStateException("Fragment tag is null."); + } + return tag; + } + private void handleLogout() { getDefaultSharedPreferences(ProfileActivity.this) .edit().clear().apply(); @@ -405,7 +454,8 @@ private void handleLogout() { } } - private static void setupNameMapping(Map mapping, String[] namesFromResources) { + private static void setupNameMapping( + Map mapping, String[] namesFromResources) { mapping.put(DRAWER_PROFILE_ID, namesFromResources[0]); mapping.put(DRAWER_EVENTS_ID, namesFromResources[1]); mapping.put(DRAWER_NEW_EVENT_ID, namesFromResources[2]); @@ -413,7 +463,6 @@ private static void setupNameMapping(Map mapping, String[] namesFr mapping.put(DRAWER_SETTINGS_ID, namesFromResources[4]); } - private static Runnable replaceFragment( FragmentManager fm, Provider fragmentP, Provider currentTagP) { return () -> { @@ -421,7 +470,8 @@ private static Runnable replaceFragment( FragmentTransaction txn = fm.beginTransaction(); //txn.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out); txn.replace(R.id.profile_activity_frame, fragmentP.get(), currentTagP.get()); - //for some reasons txn.commit leads to errors and txn.commitAllowingStateLoss doesn't + // for some reasons txn.commit leads to errors + // and txn.commitAllowingStateLoss doesn't txn.commit(); //txn.commitAllowingStateLoss(); }; @@ -544,19 +594,13 @@ private void updateDrawerIcons(IconPackEnum iconPack) { icons = iconPack; } - private static Function getIconProvider(IconPackEnum iconPack) { - Function iconProvider; - switch (iconPack) { - case FONT_AWESOME: - iconProvider = ProfileActivity::fontAwesomeIconPack; - break; - case GOOGLE_MATERIALS: - iconProvider = ProfileActivity::googleMaterialIconPack; - break; - default: - iconProvider = ProfileActivity::fontAwesomeIconPack; - } - return iconProvider; + private static Function getIconProvider( + IconPackEnum iconPack) { + return switch (iconPack) { + case FONT_AWESOME -> ProfileActivity::fontAwesomeIconPack; + case GOOGLE_MATERIALS -> ProfileActivity::googleMaterialIconPack; + default -> ProfileActivity::fontAwesomeIconPack; + }; } private static IIcon googleMaterialIconPack(Long id) { @@ -626,7 +670,8 @@ private static IIcon fontAwesomeIconPack(Long id) { return FontAwesome.Icon.faw_coffee; } - private static void updateIconFor(Drawer drawer, Function iconProvider, long itemId) { + private static void updateIconFor( + Drawer drawer, Function iconProvider, long itemId) { IDrawerItem iDrawerItem = drawer.getDrawerItem(itemId); if (iDrawerItem == null) { Log.d(TAG, "Drawer item is not exist " + itemId); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/event/database/EventDatabase.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/event/database/EventDatabase.java index 3dd122d..ec7f097 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/event/database/EventDatabase.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/event/database/EventDatabase.java @@ -4,8 +4,15 @@ import androidx.room.RoomDatabase; import com.tom.meeter.context.profile.repository.event.domain.Event; +import com.tom.meeter.context.profile.repository.user.domain.User; -@Database(entities = {Event.class}, version = 1) +@Database( + entities = { + Event.class, + User.class + }, + version = 1 +) public abstract class EventDatabase extends RoomDatabase { public abstract EventDao eventDao(); } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/event/domain/Event.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/event/domain/Event.java index fca3c8d..dff93aa 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/event/domain/Event.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/repository/event/domain/Event.java @@ -1,7 +1,5 @@ package com.tom.meeter.context.profile.repository.event.domain; -import static androidx.room.ForeignKey.CASCADE; - import androidx.annotation.NonNull; import androidx.room.Entity; import androidx.room.ForeignKey; @@ -9,7 +7,14 @@ import com.tom.meeter.context.profile.repository.user.domain.User; -@Entity +@Entity( + foreignKeys = @ForeignKey( + entity = User.class, + parentColumns = "id", + childColumns = "creatorId", + onDelete = ForeignKey.CASCADE + ) +) public class Event { @PrimaryKey @@ -19,17 +24,15 @@ public class Event { private String description; private double latitude; private double longitude; - - @ForeignKey(entity = User.class, parentColumns = "id", childColumns = "creatorId", - onDelete = CASCADE) private String creatorId; private String created; private String starting; private String ending; - public Event(@NonNull String id, String name, String description, double latitude, - double longitude, String creatorId, String created, String starting, - String ending) { + public Event( + @NonNull String id, String name, String description, + double latitude, double longitude, String creatorId, + String created, String starting, String ending) { this.id = id; this.name = name; this.description = description; diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/common/InfrastructureHelper.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/common/InfrastructureHelper.java index 9cac81c..79b0adf 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/common/InfrastructureHelper.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/common/InfrastructureHelper.java @@ -12,6 +12,8 @@ import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; +import java.util.Arrays; + public class InfrastructureHelper { private static final String METHOD_ENDING = "()"; @@ -46,6 +48,16 @@ public static void logMethod(String tag, Object obj) { } } + public static void logMethod(String tag, Object obj, Object... args) { + if (obj.getClass().isAnonymousClass()) { + Log.d(tag, obj.getClass().getName() + " " + getCurrentMethodName() + + " with args: " + Arrays.toString(args)); + } else { + Log.d(tag, obj.getClass().getSimpleName() + " " + getCurrentMethodName() + + " with args: " + Arrays.toString(args)); + } + } + public static void logMethod(String tag, String name) { Log.d(tag, name + " " + getCurrentMethodName()); } diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/utils/Utils.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/utils/Utils.java new file mode 100644 index 0000000..1240835 --- /dev/null +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/utils/Utils.java @@ -0,0 +1,12 @@ +package com.tom.meeter.infrastructure.utils; + +public class Utils { + private Utils() { + } + + public static T requireNonNull(T me, String message) { + if (me == null) throw new IllegalStateException(message); + return me; + } + +} diff --git a/AndroidClient/src/main/res/layout/profile_activity.xml b/AndroidClient/src/main/res/layout/profile_activity.xml index 8bf7c1c..c50e59c 100644 --- a/AndroidClient/src/main/res/layout/profile_activity.xml +++ b/AndroidClient/src/main/res/layout/profile_activity.xml @@ -7,8 +7,8 @@ + android:elevation="4dp" + android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> - - - - - + + + + + @@ -32,11 +32,10 @@ android:id="@+id/profile_activity_frame" android:layout_width="match_parent" android:layout_height="match_parent" - app:layout_behavior="@string/appbar_scrolling_view_behavior"> - + app:layout_behavior="@string/appbar_scrolling_view_behavior" /> - - - - + + + + \ No newline at end of file diff --git a/AndroidClient/src/main/res/values-ru-rRU/strings.xml b/AndroidClient/src/main/res/values-ru-rRU/strings.xml index 7a1aafb..b60206d 100644 --- a/AndroidClient/src/main/res/values-ru-rRU/strings.xml +++ b/AndroidClient/src/main/res/values-ru-rRU/strings.xml @@ -2,7 +2,7 @@ Meeter Настройки - Профиль + Meeter Логин Пароль Повторите пароль diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 03095f2..c81940c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agp = "8.10.1" +agp = "8.11.0" #android appcompat = "1.7.1" @@ -15,17 +15,17 @@ material = "1.12.0" #Core playServicesMaps = "19.2.0" retrofit = "3.0.0" -room = "2.0.0" -dagger = "2.56" +room = "2.7.2" +dagger = "2.56.2" eventbus = "3.3.1" guava = "33.4.8-android" materialdrawer = "6.1.2" okhttp = "4.12.0" rxandroid = "2.1.1" -rxjava = "2.2.6" +rxjava = "2.2.21" socketIoClient = "2.1.2" -jackson = "2.19.0" +jackson = "2.19.1" desugar_jdk_libs = "2.1.5" @@ -35,8 +35,6 @@ junit = "4.13.2" #junitVersion = "1.2.1" #espressoCore = "3.6.1" -#appcompat = "1.6.1" -#material = "1.10.0" #constraintlayout = "2.1.4" #lifecycleLivedataKtx = "2.9.0" #lifecycleViewmodelKtx = "2.9.0" @@ -87,7 +85,6 @@ junit-junit = { module = "junit:junit", version.ref = "junit" } #ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } #espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } -#material = { group = "com.google.android.material", name = "material", version.ref = "material" } #constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" } #lifecycle-livedata-ktx = { group = "androidx.lifecycle", name = "lifecycle-livedata-ktx", version.ref = "lifecycleLivedataKtx" } #lifecycle-viewmodel-ktx = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycleViewmodelKtx" } From 8ab48dfa97dd0e2f706beea8652a6f2ca1e7eb0a Mon Sep 17 00:00:00 2001 From: Georgy Lebedik Date: Sat, 28 Jun 2025 14:56:51 +0300 Subject: [PATCH 24/32] CreateNewEvent refactoring. --- AndroidClient/src/main/AndroidManifest.xml | 1 + .../java/com/tom/meeter/AppComponent.java | 3 + .../activity/EventLocationMapActivity.java | 7 +- .../event/activity/ProfileEventActivity.java | 24 +- .../network/domain/CreateNewEventAttempt.java | 54 --- .../network/domain/SearchForEvents.java | 2 +- .../network/service/SocketIOService.java | 34 -- .../activity/NewEventOnMapActivity.java | 150 ++++++ .../fragment/CreateNewEventFragment.java | 438 ++++++++---------- .../profile/fragment/GoogleMapsFragment.java | 2 +- .../profile/message/PublishEventRequest.java | 105 +++++ .../profile/service/ProfileService.java | 6 + .../meeter/context/profile/utils/Utils.java | 35 ++ .../infrastructure/common/CommonHelper.java | 7 + .../infrastructure/common/DateHelper.java | 94 ++-- .../common/InfrastructureHelper.java | 14 + .../eventbus/events/BaseIdEvent.java | 13 - .../eventbus/events/FailureEventCreation.java | 4 - .../events/SuccessfulEventCreation.java | 8 - .../main/res/layout/fragment_new_event.xml | 28 +- .../src/main/res/values-en/strings.xml | 8 + .../src/main/res/values-ru-rRU/strings.xml | 8 + AndroidClient/src/main/res/values/strings.xml | 8 + 23 files changed, 657 insertions(+), 396 deletions(-) delete mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/network/domain/CreateNewEventAttempt.java create mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/NewEventOnMapActivity.java create mode 100644 AndroidClient/src/main/java/com/tom/meeter/context/profile/message/PublishEventRequest.java delete mode 100644 AndroidClient/src/main/java/com/tom/meeter/infrastructure/eventbus/events/BaseIdEvent.java delete mode 100644 AndroidClient/src/main/java/com/tom/meeter/infrastructure/eventbus/events/FailureEventCreation.java delete mode 100644 AndroidClient/src/main/java/com/tom/meeter/infrastructure/eventbus/events/SuccessfulEventCreation.java diff --git a/AndroidClient/src/main/AndroidManifest.xml b/AndroidClient/src/main/AndroidManifest.xml index 6c36365..9227167 100644 --- a/AndroidClient/src/main/AndroidManifest.xml +++ b/AndroidClient/src/main/AndroidManifest.xml @@ -94,6 +94,7 @@ + (this, onNotAuthenticated) { @Override - public void onResponse(Call call, Response resp) { + public void onResponse( + Call call, Response resp) { super.onResponse(call, resp); - if (resp.code() == HttpCodes.OK) { - String oldPhotoPath = eventCache.getPhotoPath(); - eventCache = resp.body(); - if (!Objects.equals(oldPhotoPath, eventCache.getPhotoPath())) { - downloadAndUpdateLayoutPhoto(eventCache.getPhotoPath()); - } - showMessage(ProfileEventActivity.this, R.string.saved); + if (resp.code() != HttpCodes.OK) { + updateLayout(); + return; + } + String oldPhotoPath = eventCache.getPhotoPath(); + eventCache = resp.body(); + if (!Objects.equals(oldPhotoPath, eventCache.getPhotoPath())) { + downloadAndUpdateLayoutPhoto(eventCache.getPhotoPath()); } + showMessage(ProfileEventActivity.this, R.string.saved); updateLayout(); } }); diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/network/domain/CreateNewEventAttempt.java b/AndroidClient/src/main/java/com/tom/meeter/context/network/domain/CreateNewEventAttempt.java deleted file mode 100644 index 994117f..0000000 --- a/AndroidClient/src/main/java/com/tom/meeter/context/network/domain/CreateNewEventAttempt.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.tom.meeter.context.network.domain; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.time.OffsetDateTime; - -public class CreateNewEventAttempt implements NetworkEvent { - - private final String name; - private final String description; - private final OffsetDateTime starting; - private final OffsetDateTime ending; - private final Double latitude; - private final Double longitude; - - public CreateNewEventAttempt( - String name, String description, OffsetDateTime starting, - OffsetDateTime ending, Double latitude, Double longitude) { - this.name = name; - this.description = description; - this.starting = starting; - this.ending = ending; - this.latitude = latitude; - this.longitude = longitude; - } - - @Override - public JSONObject toJson() { - try { - return new JSONObject() - .put("name", name) - .put("description", description) - .put("starting", starting) - .put("ending", ending) - .put("latitude", latitude) - .put("longitude", longitude); - } catch (JSONException e) { - throw new RuntimeException("Unable to call CreateNewEventAttempt.toJson(): ", e); - } - } - - @Override - public String toString() { - return "CreateNewEventAttempt{" + - "name='" + name + - ", description='" + description + - ", starting=" + starting + - ", ending=" + ending + - ", latitude=" + latitude + - ", longitude=" + longitude + - '}'; - } -} diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/network/domain/SearchForEvents.java b/AndroidClient/src/main/java/com/tom/meeter/context/network/domain/SearchForEvents.java index 3422494..dd63265 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/network/domain/SearchForEvents.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/network/domain/SearchForEvents.java @@ -9,7 +9,7 @@ * Created by Tom on 14.01.2017. */ -public record SearchForEvents(float latitude, float longitude, int distance) +public record SearchForEvents(double latitude, double longitude, int distance) implements NetworkEvent { private static final String LATITUDE_KEY = "latitude"; diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/network/service/SocketIOService.java b/AndroidClient/src/main/java/com/tom/meeter/context/network/service/SocketIOService.java index 8cd3cb2..0ea9bf6 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/network/service/SocketIOService.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/network/service/SocketIOService.java @@ -19,15 +19,11 @@ import android.os.IBinder; import android.util.Log; -import com.tom.meeter.context.network.domain.CreateNewEventAttempt; import com.tom.meeter.context.network.domain.SearchForEvents; import com.tom.meeter.context.network.dto.EventDTO; import com.tom.meeter.context.network.dto.UserDTO; import com.tom.meeter.infrastructure.common.Globals; -import com.tom.meeter.infrastructure.common.JsonHelper; -import com.tom.meeter.infrastructure.eventbus.events.FailureEventCreation; import com.tom.meeter.infrastructure.eventbus.events.IncomeEvents; -import com.tom.meeter.infrastructure.eventbus.events.SuccessfulEventCreation; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; @@ -53,7 +49,6 @@ public class SocketIOService extends Service { private static final String TAG = SocketIOService.class.getCanonicalName(); private static final String GREETINGS_CHANNEL = "greetings"; - private static final String EVENTS_CREATE_CHANNEL = "events:create"; private static final String EVENTS_SEARCH_CHANNEL = "events:search"; private static final String EVENTS_NOTIFICATIONS_CHANNEL = "events:notifications"; private static final String NEW_SUBSCRIBER_CHANNEL = "user:subscription:new"; @@ -186,7 +181,6 @@ private void initializeSocketClient( socketClient.on(EVENTS_SEARCH_CHANNEL, SocketIOService::eventsSearchHandler); socketClient.on(EVENTS_NOTIFICATIONS_CHANNEL, this::eventsNotificationsChannel); socketClient.on(NEW_SUBSCRIBER_CHANNEL, this::newSubscriberNotificationsChannel); - socketClient.on(EVENTS_CREATE_CHANNEL, SocketIOService::eventsCreateHandler); socketClient.connect(); EventBus.getDefault().register(this); Log.d(TAG, "SocketIOClient is going to start... connected? {" @@ -220,7 +214,6 @@ private void disconnect() { socketClient.off(EVENTS_SEARCH_CHANNEL, SocketIOService::eventsSearchHandler); socketClient.off(EVENTS_NOTIFICATIONS_CHANNEL, this::eventsNotificationsChannel); socketClient.off(NEW_SUBSCRIBER_CHANNEL, this::newSubscriberNotificationsChannel); - socketClient.off(EVENTS_CREATE_CHANNEL, SocketIOService::eventsCreateHandler); initialized = false; } @@ -230,12 +223,6 @@ public void onMessageEvent(SearchForEvents event) { socketClient.emit(EVENTS_SEARCH_CHANNEL, event.toJson()); } - @Subscribe - public void onMessageEvent(CreateNewEventAttempt event) { - Log.d(TAG, "onMessageEvent:CreateNewEventAttempt: " + event.toString()); - socketClient.emit(EVENTS_CREATE_CHANNEL, event.toJson()); - } - private static String readFlags(int flags) { if ((flags & START_FLAG_REDELIVERY) == START_FLAG_REDELIVERY) return "START_FLAG_REDELIVERY"; @@ -315,25 +302,4 @@ private static boolean validateSingleMessageResponse(Class aClass, Object... } return true; } - - private static void eventsCreateHandler(Object... args) { - JSONObject response = getSimpleResponse(JSONObject.class, args); - int code = JsonHelper.getInt(response, CODE_KEY); - Log.d(TAG, EVENTS_CREATE_CHANNEL + " : " + response); - switch (code) { - case CREATED_CODE: - Log.d(TAG, "Event successfully created. " + response); - EventBus.getDefault() - .post(new SuccessfulEventCreation(JsonHelper.getString(response, ID_KEY))); - break; - case BAD_REQUEST: - Log.d(TAG, "Failed event creation. " + response); - EventBus.getDefault().post(new FailureEventCreation()); - break; - default: - Log.d(TAG, "Unrecognized code from " + EVENTS_CREATE_CHANNEL + " [" + code + "]"); - break; - } - } } - diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/NewEventOnMapActivity.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/NewEventOnMapActivity.java new file mode 100644 index 0000000..cf3c355 --- /dev/null +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/activity/NewEventOnMapActivity.java @@ -0,0 +1,150 @@ +package com.tom.meeter.context.profile.activity; + +import static com.tom.meeter.context.profile.fragment.GoogleMapsFragment.ZOOM_VALUE; +import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.location.Location; +import android.os.Bundle; +import android.os.IBinder; +import android.util.Log; +import android.widget.Toast; + +import androidx.appcompat.app.AppCompatActivity; + +import com.google.android.gms.maps.CameraUpdateFactory; +import com.google.android.gms.maps.GoogleMap; +import com.google.android.gms.maps.OnMapReadyCallback; +import com.google.android.gms.maps.SupportMapFragment; +import com.google.android.gms.maps.UiSettings; +import com.google.android.gms.maps.model.LatLng; +import com.google.android.gms.maps.model.Marker; +import com.google.android.gms.maps.model.MarkerOptions; +import com.tom.meeter.R; +import com.tom.meeter.context.event.activity.EventLocationMapActivity; +import com.tom.meeter.context.gps.domain.LocationTrackerListener; +import com.tom.meeter.context.gps.service.LocationTrackerService; +import com.tom.meeter.databinding.ActivityEventPositionBinding; + +public class NewEventOnMapActivity extends AppCompatActivity + implements OnMapReadyCallback { + + public static final String EXTRA_LAT = "extra_lat"; + public static final String EXTRA_LNG = "extra_lng"; + + private static final String TAG = EventLocationMapActivity.class.getCanonicalName(); + private Marker eventMarker; + private GoogleMap gmap; + + private ServiceConnection locationServiceConn; + private LocationTrackerService locationService; + private boolean cameraMoved = false; + + private LocationTrackerListener singleLocationUpdateListener; + private LatLng userLocation; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + ActivityEventPositionBinding binding = + ActivityEventPositionBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + + SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager() + .findFragmentById(R.id.eventSelectPosition); + if (mapFragment != null) { + mapFragment.getMapAsync(this); + } + binding.btnConfirm.setOnClickListener(v -> { + if (eventMarker != null) { + Intent resultIntent = new Intent(); + LatLng position = eventMarker.getPosition(); + resultIntent.putExtra(EXTRA_LAT, position.latitude); + resultIntent.putExtra(EXTRA_LNG, position.longitude); + setResult(RESULT_OK, resultIntent); + finish(); + } else { + Toast.makeText(this, R.string.select_point_on_the_map, Toast.LENGTH_SHORT) + .show(); + } + }); + } + + private void setupSingleLocationListener() { + singleLocationUpdateListener = new LocationTrackerListener() { + @Override + public void onLocationChanged(Location location) { + logMethod(TAG, this); + if (gmap != null && !cameraMoved) { + userLocation = new LatLng(location.getLatitude(), location.getLongitude()); + gmap.moveCamera(CameraUpdateFactory.newLatLngZoom(userLocation, ZOOM_VALUE)); + cameraMoved = true; + locationService.removeLocationTrackerListener(this); + singleLocationUpdateListener = null; + unbindService(locationServiceConn); + locationService = null; + locationServiceConn = null; + } + } + }; + locationServiceConn = new ServiceConnection() { + public void onServiceConnected(ComponentName name, IBinder binder) { + logMethod(TAG, this); + locationService = ((LocationTrackerService.ServiceBinder) binder).getService(); + locationService.addLocationTrackerListener(singleLocationUpdateListener); + } + + public void onServiceDisconnected(ComponentName name) { + logMethod(TAG, this); + locationService = null; + locationServiceConn = null; + } + }; + Intent service = new Intent(this, LocationTrackerService.class); + bindService(service, locationServiceConn, BIND_AUTO_CREATE); + } + + @Override + public void onMapReady(GoogleMap googleMap) { + gmap = googleMap; + UiSettings uiSettings = gmap.getUiSettings(); + uiSettings.setZoomControlsEnabled(true); + + gmap.setOnMapClickListener( + latLng -> { + if (eventMarker != null) { + eventMarker.setPosition(latLng); + return; + } + if (userLocation != null) { + eventMarker = gmap.addMarker(new MarkerOptions().position(latLng)); + } + Log.d(TAG, "Event marker is null, user location" + + " is null, nothing to do..."); + }); + setupSingleLocationListener(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + logMethod(TAG, this); + if (locationService != null && singleLocationUpdateListener != null) { + locationService.removeLocationTrackerListener(singleLocationUpdateListener); + } + if (locationServiceConn != null) { + unbindService(locationServiceConn); + } + } + + public static void dispatchToNewEventOnMapActivity(Context ctx) { + ctx.startActivity(createNewEventOnMapActivityIntent(ctx)); + } + + public static Intent createNewEventOnMapActivityIntent(Context ctx) { + return new Intent(ctx, NewEventOnMapActivity.class); + } +} diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/CreateNewEventFragment.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/CreateNewEventFragment.java index 2f175b0..0ab0b69 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/CreateNewEventFragment.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/CreateNewEventFragment.java @@ -1,11 +1,22 @@ package com.tom.meeter.context.profile.fragment; +import static android.app.Activity.RESULT_OK; import static android.content.Context.BIND_AUTO_CREATE; -import static com.tom.meeter.infrastructure.common.CommonHelper.EMPTY_STR; -import static com.tom.meeter.infrastructure.common.DateHelper.DATE_FORMAT; +import static com.tom.meeter.context.event.activity.EventLocationMapActivity.EXTRA_LAT; +import static com.tom.meeter.context.event.activity.EventLocationMapActivity.EXTRA_LNG; +import static com.tom.meeter.context.event.activity.ProfileEventActivity.dispatchToProfileEventActivity; +import static com.tom.meeter.context.profile.activity.NewEventOnMapActivity.createNewEventOnMapActivityIntent; +import static com.tom.meeter.context.profile.utils.Utils.createPublishEventRequest; +import static com.tom.meeter.infrastructure.common.CommonHelper.isEmpty; +import static com.tom.meeter.infrastructure.common.DateHelper.isDateValid; +import static com.tom.meeter.infrastructure.common.DateHelper.setCurrentDate; +import static com.tom.meeter.infrastructure.common.DateHelper.setCurrentTime; +import static com.tom.meeter.infrastructure.common.DateHelper.showDatePicker; +import static com.tom.meeter.infrastructure.common.DateHelper.showTimePicker; import static com.tom.meeter.infrastructure.common.InfrastructureHelper.logMethod; +import static com.tom.meeter.infrastructure.common.InfrastructureHelper.showMessage; -import android.annotation.SuppressLint; +import android.accounts.AccountManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -15,35 +26,35 @@ import android.os.IBinder; import android.text.Editable; import android.text.TextWatcher; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; +import androidx.activity.result.ActivityResultLauncher; +import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.Fragment; +import com.tom.meeter.App; import com.tom.meeter.R; +import com.tom.meeter.context.auth.infrastructure.AuthHelper; import com.tom.meeter.context.gps.service.LocationTrackerService; -import com.tom.meeter.context.network.domain.CreateNewEventAttempt; +import com.tom.meeter.context.network.dto.EventDTO; +import com.tom.meeter.context.profile.message.PublishEventRequest; +import com.tom.meeter.context.profile.service.ProfileService; import com.tom.meeter.databinding.FragmentNewEventBinding; -import com.tom.meeter.infrastructure.eventbus.events.FailureEventCreation; -import com.tom.meeter.infrastructure.eventbus.events.SuccessfulEventCreation; - -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; -import org.greenrobot.eventbus.ThreadMode; - -import java.text.ParseException; -import java.time.LocalDate; -import java.time.LocalTime; -import java.time.OffsetDateTime; -import java.time.ZoneOffset; -import java.time.format.DateTimeFormatter; -import java.util.Calendar; -import java.util.Date; +import com.tom.meeter.infrastructure.common.InfrastructureHelper; +import com.tom.meeter.infrastructure.http.BaseOnNotAuthenticatedCallback; +import com.tom.meeter.infrastructure.http.HttpCodes; + +import javax.inject.Inject; + +import retrofit2.Call; +import retrofit2.Response; /** * Created by Tom on 14.12.2016. @@ -51,13 +62,15 @@ public class CreateNewEventFragment extends Fragment { private static final String TAG = CreateNewEventFragment.class.getCanonicalName(); - private static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern("HH:mm"); - FragmentNewEventBinding binding; + @Inject + ProfileService service; - private ServiceConnection locationServiceConnection; + private FragmentNewEventBinding binding; + private ServiceConnection sConn; private LocationTrackerService locationService; - + private AccountManager accountManager; + private ActivityResultLauncher mapResult; public CreateNewEventFragment() { logMethod(TAG, this); @@ -67,7 +80,13 @@ public CreateNewEventFragment() { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); logMethod(TAG, this); - locationServiceConnection = new ServiceConnection() { + + ((App) getActivity().getApplication()).getComponent().inject(this); + + Context ctx = requireContext(); + accountManager = AccountManager.get(ctx); + + sConn = new ServiceConnection() { public void onServiceConnected(ComponentName name, IBinder binder) { logMethod(TAG, this); locationService = ((LocationTrackerService.ServiceBinder) binder).getService(); @@ -78,11 +97,21 @@ public void onServiceDisconnected(ComponentName name) { locationService = null; } }; - Context ctx = getContext(); - if (ctx != null) { - Intent service = new Intent(ctx, LocationTrackerService.class); - ctx.bindService(service, locationServiceConnection, BIND_AUTO_CREATE); - } + + mapResult = registerForActivityResult( + new ActivityResultContracts.StartActivityForResult(), + result -> { + if (result.getResultCode() != RESULT_OK || result.getData() == null) { + return; + } + double lat = result.getData().getDoubleExtra(EXTRA_LAT, 0.0); + double lng = result.getData().getDoubleExtra(EXTRA_LNG, 0.0); + binding.newEventLatitudeEditText.setText(String.valueOf(lat)); + binding.newEventLongitudeEditText.setText(String.valueOf(lng)); + }); + + ctx.bindService( + new Intent(ctx, LocationTrackerService.class), sConn, BIND_AUTO_CREATE); } @Nullable @@ -91,167 +120,179 @@ public View onCreateView( @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { logMethod(TAG, this); binding = FragmentNewEventBinding.inflate(inflater, container, false); + return binding.getRoot(); + } - binding.newEventOtherPlaceBtn.setOnClickListener(v -> { - //TODO: Implement otherPlaceClickHandler - }); - binding.newEventEndsOtherTimeBtn.setOnClickListener(v -> { - //TODO: - binding.newEventEndsTimeEditText.setText(null); - }); - binding.newEventStartsOtherDateBtn.setOnClickListener(v -> { - //TODO: Implement otherDateClickHandler - binding.newEventStartsDateEditText.setText(null); - }); - binding.newEventEndsOtherDateBtn.setOnClickListener(v -> { - //TODO: Implement otherDateClickHandler - binding.newEventEndsDateEditText.setText(null); - }); - binding.newEventStartsOtherTimeBtn.setOnClickListener(v -> { - //TODO: Implement otherDateClickHandler - binding.newEventStartsTimeEditText.setText(null); - }); + @Override + public void onViewCreated( + @NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + Context ctx = requireContext(); + + /* Starting */ binding.newEventStartsCurrentDateBtn.setOnClickListener( - v -> binding.newEventStartsDateEditText.setText(DATE_FORMAT.format(new Date()))); + v -> setCurrentDate(binding.newEventStartsDateEditText)); + binding.newEventStartsOtherDateBtn.setOnClickListener( + v -> showDatePicker(ctx, binding.newEventStartsDateEditText)); + binding.newEventStartsCurrentTimeBtn.setOnClickListener( + v -> setCurrentTime(binding.newEventStartsTimeEditText)); + binding.newEventStartsOtherTimeBtn.setOnClickListener( + v -> showTimePicker(ctx, binding.newEventStartsTimeEditText)); + binding.newEventStartsDateEditText.addTextChangedListener( + createDataWatcher( + binding.newEventStartsCurrentTimeBtn, + binding.newEventStartsOtherTimeBtn, + binding.newEventStartsDateTextView)); + + /* Ending */ binding.newEventEndsCurrentDateBtn.setOnClickListener( - v -> binding.newEventEndsDateEditText.setText(DATE_FORMAT.format(new Date()))); - binding.newEventStartsCurrentTimeBtn.setOnClickListener(v -> startsCurrentTimeClickHandler()); - binding.newEventEndsCurrentTimeBtn.setOnClickListener(v -> endsCurrentTimeClickHandler()); - - binding.newEventCurrentPlaceBtn.setOnClickListener(v -> currentPlaceClickHandler()); - binding.newEventCreateBtn.setOnClickListener(v -> createEventClickHandler()); + v -> setCurrentDate(binding.newEventEndsDateEditText)); + binding.newEventEndsOtherDateBtn.setOnClickListener( + v -> showDatePicker(ctx, binding.newEventEndsDateEditText)); + binding.newEventEndsCurrentTimeBtn.setOnClickListener( + v -> setCurrentTime(binding.newEventEndsTimeEditText)); + binding.newEventEndsOtherTimeBtn.setOnClickListener( + v -> showTimePicker(ctx, binding.newEventEndsTimeEditText)); + binding.newEventEndsDateEditText.addTextChangedListener( + createDataWatcher( + binding.newEventEndsCurrentTimeBtn, + binding.newEventEndsOtherTimeBtn, + binding.newEventEndsDateTextView)); + + /* Location */ + binding.newEventCurrentPlaceBtn.setOnClickListener(v -> { + Location location = locationService.getLastKnownLocation(); + if (location == null) { + showMessage(requireContext(), R.string.unable_to_get_the_location); + return; + } + binding.newEventLatitudeEditText.setText(String.valueOf(location.getLatitude())); + binding.newEventLongitudeEditText.setText(String.valueOf(location.getLongitude())); + }); + binding.newEventOtherPlaceBtn.setOnClickListener( + v -> mapResult.launch(createNewEventOnMapActivityIntent(ctx))); TextWatcher watcher = createTextWatcher(); binding.newEventLatitudeEditText.addTextChangedListener(watcher); binding.newEventLongitudeEditText.addTextChangedListener(watcher); binding.newEventNameEditText.addTextChangedListener(watcher); - binding.newEventStartsDateEditText.addTextChangedListener(createStartDataWatcher()); - binding.newEventEndsDateEditText.addTextChangedListener(createEndDataWatcher()); - - return binding.getRoot(); - } - - @NonNull - private TextWatcher createEndDataWatcher() { - return new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - - } - - @Override - public void afterTextChanged(Editable s) { - endsDateChangedListener(); - } - }; - } - - @NonNull - private TextWatcher createStartDataWatcher() { - return new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - - } - - @Override - public void afterTextChanged(Editable s) { - startsDateChangedListener(); - } - }; + binding.newEventCreateBtn.setOnClickListener(this::createEventClickHandler); } - public void startsDateChangedListener() { - String s = binding.newEventStartsDateEditText.getText().toString(); - if (!isDateValid(s)) { - binding.newEventStartsDateTextView.setText(R.string.wrong_date); - binding.newEventCreateBtn.setEnabled(false); + public void createEventClickHandler(View ign) { + PublishEventRequest req = createPublishEventRequest(binding); + if (req.isEmpty()) { + showMessage(requireContext(), R.string.empty_create_request_is_not_sent); return; } - binding.newEventStartsDateTextView.setText(R.string.correct_date); - validateWholeForm(); + service.publishEvent(AuthHelper.getAuthHeader(accountManager), req) + .enqueue(new BaseOnNotAuthenticatedCallback<>( + requireContext(), + () -> InfrastructureHelper.restartActivityFromFragment(this)) { + @Override + public void onResponse( + Call call, Response resp) { + super.onResponse(call, resp); + if (resp.code() == HttpCodes.OK && resp.body() != null) { + showEventDialog(resp.body()); + return; + } + new AlertDialog.Builder(requireContext()) + .setIcon(R.drawable.ic_meeter_lr) + .setTitle(R.string.failed) + .setMessage(R.string.failed_to_create_event) + .setPositiveButton(R.string.ok, (dialog, id) -> dialog.cancel()) + .create() + .show(); + return; + } + }); } - public void endsDateChangedListener() { - String e = binding.newEventEndsDateEditText.getText().toString(); - if (!isDateValid(e)) { - binding.newEventEndsDateTextView.setText(R.string.wrong_date); - binding.newEventCreateBtn.setEnabled(false); + private void validateWholeForm() { + if (!allSet()) { return; } - binding.newEventEndsDateTextView.setText(R.string.correct_date); - validateWholeForm(); + binding.newEventCreateBtn.setEnabled(true); } - public void locationChanges() { - CharSequence name = binding.newEventNameEditText.getText(); - CharSequence latitude = binding.newEventLatitudeEditText.getText(); - CharSequence longitude = binding.newEventLongitudeEditText.getText(); + private boolean allSet() { + return !isEmpty(binding.newEventNameEditText.getText()) + && !isEmpty(binding.newEventLatitudeEditText.getText()) + && !isEmpty(binding.newEventLongitudeEditText.getText()) + && isDateValid(binding.newEventStartsDateEditText.getText()) + && isDateValid(binding.newEventEndsDateEditText.getText()); + } - if (requiredFieldsNotProvided(name, latitude, longitude)) { - binding.newEventCreateBtn.setEnabled(false); - } else { - validateWholeForm(); - } + private void showEventDialog(EventDTO event) { + new AlertDialog.Builder(requireContext()) + .setIcon(R.drawable.ic_meeter_lr) + .setTitle(R.string.event_published) + .setMessage( + getString( + R.string.recently_created_event_is_published, + event.getName())) + .setPositiveButton( + R.string.to_event, + (dialog, which) -> dispatchToProfileEventActivity( + requireContext(), event.getId())) + .setNegativeButton( + R.string.back, + (dialog, which) -> dialog.dismiss()) + .show(); } @NonNull - private TextWatcher createTextWatcher() { - return new TextWatcher() { + private TextWatcher createDataWatcher( + Button currentTime, Button otherTime, TextView target) { + return new BaseTextWatcher() { @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - + public void afterTextChanged(Editable e) { + if (!isDateValid(e.toString())) { + target.setText(R.string.wrong_date); + binding.newEventCreateBtn.setEnabled(false); + currentTime.setEnabled(false); + otherTime.setEnabled(false); + return; + } + currentTime.setEnabled(true); + otherTime.setEnabled(true); + target.setText(R.string.correct_date); + validateWholeForm(); } + }; + } + @NonNull + private TextWatcher createTextWatcher() { + return new BaseTextWatcher() { @Override public void afterTextChanged(Editable s) { - locationChanges(); + CharSequence name = binding.newEventNameEditText.getText(); + CharSequence latitude = binding.newEventLatitudeEditText.getText(); + CharSequence longitude = binding.newEventLongitudeEditText.getText(); + + if (requiredFieldsProvided(name, latitude, longitude)) { + validateWholeForm(); + return; + } + binding.newEventCreateBtn.setEnabled(false); } }; } - @SuppressLint("SetTextI18n") - public void endsCurrentTimeClickHandler() { - binding.newEventEndsTimeEditText.setText(TIME_FORMAT.format(LocalTime.now())); - } - - @SuppressLint("SetTextI18n") - public void startsCurrentTimeClickHandler() { - binding.newEventStartsTimeEditText.setText(TIME_FORMAT.format(LocalTime.now())); - } - @Override public void onStart() { super.onStart(); logMethod(TAG, this); - EventBus.getDefault().register(this); - Log.d(TAG, "CreateNewEventFragment Event bus registered..."); - //Log.d(TAG, "Time :" + ZonedDateTime.now().toString()); } @Override public void onStop() { super.onStop(); logMethod(TAG, this); - EventBus.getDefault().unregister(this); - Log.d(TAG, "CreateNewEventFragment Event bus unregistered..."); } @Override @@ -264,105 +305,22 @@ public void onDestroyView() { public void onDestroy() { super.onDestroy(); logMethod(TAG, this); - requireContext().unbindService(locationServiceConnection); - } - - @Override - public void onAttach(Context context) { - super.onAttach(context); + requireContext().unbindService(sConn); } - public void currentPlaceClickHandler() { - Location location = locationService.getLastKnownLocation(); - if (location != null) { - binding.newEventLatitudeEditText.setText(String.valueOf(location.getLatitude())); - binding.newEventLongitudeEditText.setText(String.valueOf(location.getLongitude())); + public static abstract class BaseTextWatcher implements TextWatcher { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { } - } - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - Log.d(TAG, "requestCode = " + requestCode + ", resultCode = " + resultCode); - } - - public void createEventClickHandler() { - String startDate = binding.newEventStartsDateEditText.getText().toString(); - String startTime = binding.newEventStartsTimeEditText.getText().toString(); - LocalDate localStartDate = LocalDate.parse(startDate); - LocalTime localStartTime = LocalTime.parse(startTime); - - String endDate = binding.newEventEndsDateEditText.getText().toString(); - String endTime = binding.newEventEndsTimeEditText.getText().toString(); - LocalDate localEndDate = LocalDate.parse(endDate); - LocalTime localEndTime = LocalTime.parse(endTime); - - ZoneOffset offset = OffsetDateTime.now().getOffset(); - OffsetDateTime starts = OffsetDateTime.of(localStartDate, localStartTime, offset); - OffsetDateTime ends = OffsetDateTime.of(localEndDate, localEndTime, offset); - EventBus.getDefault() - .post(new CreateNewEventAttempt( - binding.newEventNameEditText.getText().toString(), - binding.newEventDescriptionEditText.getText().toString(), - starts, ends, - Double.valueOf(binding.newEventLatitudeEditText.getText().toString()), - Double.valueOf(binding.newEventLongitudeEditText.getText().toString()))); - } - - private static boolean requiredFieldsNotProvided( - CharSequence name, CharSequence latitude, CharSequence longitude) { - return name == null || EMPTY_STR.equals(name.toString()) - || latitude == null || EMPTY_STR.equals(latitude.toString()) - || longitude == null || EMPTY_STR.equals(longitude.toString()); - } - private void validateWholeForm() { - if (allSet()) { - binding.newEventCreateBtn.setEnabled(true); - } - } - - private boolean allSet() { - return binding.newEventNameEditText.getText() != null - && !EMPTY_STR.equals(binding.newEventNameEditText.getText().toString()) - && binding.newEventLatitudeEditText.getText() != null - && !EMPTY_STR.equals(binding.newEventLatitudeEditText.getText().toString()) - && binding.newEventLongitudeEditText.getText() != null - && !EMPTY_STR.equals(binding.newEventLongitudeEditText.getText().toString()) - && isDateValid(binding.newEventStartsDateEditText.getText().toString()) - && isDateValid(binding.newEventEndsDateEditText.getText().toString()); - } - - private static boolean isDateValid(String date) { - try { - Calendar.getInstance().setTime(DATE_FORMAT.parse(date)); - } catch (ParseException e) { - return false; + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { } - return true; - } - @Subscribe(threadMode = ThreadMode.MAIN) - public void onMessageEvent(SuccessfulEventCreation ev) { - Log.d(TAG, ev.toString()); - new AlertDialog.Builder(requireContext()) - .setTitle("Event created, id: " + ev.getId()) - .setMessage("Created.") - .setNegativeButton(getString(R.string.ok), (dialog, id) -> dialog.cancel()) - .create() - .show(); - /*startActivity(new Intent(RegistrationActivity.this, ProfileActivity.class - .putExtra(USER_ID_KEY, ev.getUserId()));*/ } - @Subscribe(threadMode = ThreadMode.MAIN) - public void onMessageEvent(FailureEventCreation ev) { - Log.d(TAG, ev.toString()); - new AlertDialog.Builder(getContext()) - .setTitle("Failed to create event") - .setMessage("Failed.") - .setNegativeButton(getString(R.string.ok), (dialog, id) -> dialog.cancel()) - .create() - .show(); + private static boolean requiredFieldsProvided( + CharSequence name, CharSequence latitude, CharSequence longitude) { + return !isEmpty(name) && !isEmpty(latitude) && !isEmpty(longitude); } } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/GoogleMapsFragment.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/GoogleMapsFragment.java index cd29265..8c8eaa5 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/GoogleMapsFragment.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/fragment/GoogleMapsFragment.java @@ -410,7 +410,7 @@ private static CircleOptions getCircleOptions(LatLng center, int searchArea) { private static void searchForEvents(double latitude, double longitude, int searchArea) { if (searchArea > 0) { EventBus.getDefault() - .post(new SearchForEvents((float) latitude, (float) longitude, searchArea)); + .post(new SearchForEvents(latitude, longitude, searchArea)); } } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/message/PublishEventRequest.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/message/PublishEventRequest.java new file mode 100644 index 0000000..0f3991d --- /dev/null +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/message/PublishEventRequest.java @@ -0,0 +1,105 @@ +package com.tom.meeter.context.profile.message; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.time.OffsetDateTime; + +public class PublishEventRequest { + + private final String PHOTO_PATH_KEY = "photo_path"; + + private String name; + private String description; + private OffsetDateTime starting; + private OffsetDateTime ending; + private String city; + private Double latitude; + private Double longitude; + @JsonProperty(value = PHOTO_PATH_KEY) + private String photoPath; + + public PublishEventRequest() { + } + + public PublishEventRequest( + String name, String description, OffsetDateTime starting, OffsetDateTime ending, + String city, Double latitude, Double longitude, String photoPath) { + this.name = name; + this.description = description; + this.starting = starting; + this.ending = ending; + this.city = city; + this.latitude = latitude; + this.longitude = longitude; + this.photoPath = photoPath; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public OffsetDateTime getStarting() { + return starting; + } + + public OffsetDateTime getEnding() { + return ending; + } + + public String getCity() { + return city; + } + + public Double getLatitude() { + return latitude; + } + + public Double getLongitude() { + return longitude; + } + + public String getPhotoPath() { + return photoPath; + } + + public void setName(String name) { + this.name = name; + } + + public void setDescription(String description) { + this.description = description; + } + + public void setStarting(OffsetDateTime starting) { + this.starting = starting; + } + + public void setEnding(OffsetDateTime ending) { + this.ending = ending; + } + + public void setCity(String city) { + this.city = city; + } + + public void setLatitude(Double latitude) { + this.latitude = latitude; + } + + public void setLongitude(Double longitude) { + this.longitude = longitude; + } + + public void setPhotoPath(String photoPath) { + this.photoPath = photoPath; + } + + public boolean isEmpty() { + return name == null && description == null && starting == null && ending == null + && city == null && latitude == null && longitude == null && photoPath == null; + } +} diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/service/ProfileService.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/service/ProfileService.java index 848899b..2b54b4f 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/service/ProfileService.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/service/ProfileService.java @@ -4,6 +4,7 @@ import com.tom.meeter.context.network.dto.EventDTO; import com.tom.meeter.context.network.dto.UserDTO; +import com.tom.meeter.context.profile.message.PublishEventRequest; import com.tom.meeter.context.profile.message.UpdateProfileRequest; import java.util.List; @@ -13,6 +14,7 @@ import retrofit2.http.GET; import retrofit2.http.Header; import retrofit2.http.PATCH; +import retrofit2.http.POST; public interface ProfileService { @GET("/profile") @@ -30,4 +32,8 @@ Call updateProfile( @GET("/profile/subscriptions") Call> getMySubscriptions(@Header(AUTH_HEADER) String authHeader); + + @POST("/event") + Call publishEvent( + @Header(AUTH_HEADER) String authHeader, @Body PublishEventRequest req); } diff --git a/AndroidClient/src/main/java/com/tom/meeter/context/profile/utils/Utils.java b/AndroidClient/src/main/java/com/tom/meeter/context/profile/utils/Utils.java index 6aa4403..d204f09 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/context/profile/utils/Utils.java +++ b/AndroidClient/src/main/java/com/tom/meeter/context/profile/utils/Utils.java @@ -1,13 +1,19 @@ package com.tom.meeter.context.profile.utils; +import static com.tom.meeter.infrastructure.common.CommonHelper.getDoubleOrNull; import static com.tom.meeter.infrastructure.common.CommonHelper.getLocalDateOrNull; import static com.tom.meeter.infrastructure.common.CommonHelper.getStringOrNull; import com.tom.meeter.context.network.dto.UserDTO; +import com.tom.meeter.context.profile.message.PublishEventRequest; import com.tom.meeter.context.profile.message.UpdateProfileRequest; +import com.tom.meeter.databinding.FragmentNewEventBinding; import com.tom.meeter.databinding.FragmentProfileBinding; import java.time.LocalDate; +import java.time.LocalTime; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; import java.util.Objects; public class Utils { @@ -40,4 +46,33 @@ public static UpdateProfileRequest createUpdateProfileRequest( } return req; } + + public static PublishEventRequest createPublishEventRequest( + FragmentNewEventBinding binding) { + //TODO in case of nulls... + String startDate = binding.newEventStartsDateEditText.getText().toString(); + String startTime = binding.newEventStartsTimeEditText.getText().toString(); + LocalDate localStartDate = LocalDate.parse(startDate); + LocalTime localStartTime = LocalTime.parse(startTime); + + String endDate = binding.newEventEndsDateEditText.getText().toString(); + String endTime = binding.newEventEndsTimeEditText.getText().toString(); + LocalDate localEndDate = LocalDate.parse(endDate); + LocalTime localEndTime = LocalTime.parse(endTime); + + ZoneOffset offset = OffsetDateTime.now().getOffset(); + OffsetDateTime starts = OffsetDateTime.of(localStartDate, localStartTime, offset); + OffsetDateTime ends = OffsetDateTime.of(localEndDate, localEndTime, offset); + + return new PublishEventRequest( + getStringOrNull(binding.newEventNameEditText.getText()), + getStringOrNull(binding.newEventDescriptionEditText.getText()), + starts, + ends, + getStringOrNull(binding.city.getText()), + getDoubleOrNull(binding.newEventLatitudeEditText.getText()), + getDoubleOrNull(binding.newEventLongitudeEditText.getText()), + null//getStringOrNull(binding.photoPath.getText()) + ); + } } diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/common/CommonHelper.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/common/CommonHelper.java index c3b629b..939ce95 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/common/CommonHelper.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/common/CommonHelper.java @@ -27,6 +27,9 @@ private CommonHelper() { public static final DateTimeFormatter UI_DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + public static final DateTimeFormatter UI_TIME_FORMAT = + DateTimeFormatter.ofPattern("HH:mm"); + public static final String EMPTY_STR = ""; public static String genderResolver(Context ctx, UserDTO.UserGender gender) { @@ -59,6 +62,10 @@ public static String getStringOrNull(CharSequence input) { return input.toString(); } + public static boolean isEmpty(CharSequence input) { + return input == null || EMPTY_STR.contentEquals(input); + } + public static Float getFloatOrNull(CharSequence input) { if (input == null || EMPTY_STR.contentEquals(input)) { return null; diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/common/DateHelper.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/common/DateHelper.java index 75a6032..d9e185d 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/common/DateHelper.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/common/DateHelper.java @@ -1,7 +1,9 @@ package com.tom.meeter.infrastructure.common; import static com.tom.meeter.infrastructure.common.CommonHelper.EMPTY_STR; +import static com.tom.meeter.infrastructure.common.CommonHelper.UI_DATE_FORMAT; import static com.tom.meeter.infrastructure.common.CommonHelper.UI_DATE_TIME_FORMAT; +import static com.tom.meeter.infrastructure.common.CommonHelper.UI_TIME_FORMAT; import android.app.DatePickerDialog; import android.app.TimePickerDialog; @@ -15,7 +17,6 @@ import com.google.android.material.datepicker.DateValidatorPointForward; import com.google.android.material.datepicker.MaterialDatePicker; -import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.LocalDateTime; @@ -28,35 +29,10 @@ public final class DateHelper { private static final String TAG = DateHelper.class.getCanonicalName(); - public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); private DateHelper() { } - public static String getAgeFromDateOld(String date) { - if (date == null) { - return ""; - } - - Calendar dob = Calendar.getInstance(); - Calendar today = Calendar.getInstance(); - - try { - dob.setTime(DATE_FORMAT.parse(date)); - } catch (ParseException e) { - Log.e(TAG, e.getLocalizedMessage(), e); - return null; - } - - int age = today.get(Calendar.YEAR) - dob.get(Calendar.YEAR); - - if (today.get(Calendar.DAY_OF_YEAR) < dob.get(Calendar.DAY_OF_YEAR)) { - age--; - } - - return String.valueOf(age); - } - public static String getAgeFromDate(LocalDate birthDate) { if (birthDate == null) { @@ -192,4 +168,70 @@ public static void showDateTimePicker(Context ctx, EditText target) { datePickerDialog.show(); } + + public static void showDatePicker(Context ctx, EditText target) { + LocalDate nowDate = LocalDate.now(); + + DatePickerDialog datePickerDialog = new DatePickerDialog( + ctx, + (view, year, month, dayOfMonth) -> { + LocalDate selectedDate = LocalDate.of(year, month + 1, dayOfMonth); + String formatted = selectedDate.format(UI_DATE_FORMAT); + target.setText(formatted); + }, + nowDate.getYear(), + nowDate.getMonthValue() - 1, + nowDate.getDayOfMonth() + ); + + datePickerDialog.show(); + } + + public static void showTimePicker(Context ctx, EditText target) { + LocalTime nowTime = LocalTime.now(); + + TimePickerDialog timePickerDialog = new TimePickerDialog( + ctx, + (timeView, hourOfDay, minute) -> { + LocalTime selectedTime = LocalTime.of(hourOfDay, minute); + String formatted = selectedTime.format(UI_TIME_FORMAT); + target.setText(formatted); + }, + nowTime.getHour(), + nowTime.getMinute(), + true + ); + + timePickerDialog.show(); + } + + public static boolean isDateValid(CharSequence date) { + return isDateValid(date.toString()); + } + + public static boolean isDateValid(String date) { + try { + LocalDate.parse(date, UI_DATE_FORMAT); + } catch (DateTimeParseException e) { + return false; + } + return true; + } + + public static String getCurrentTime() { + return UI_TIME_FORMAT.format(LocalTime.now()); + } + + public static String getCurrentDate() { + return LocalDate.now().format(UI_DATE_FORMAT); + } + + public static void setCurrentTime(EditText target) { + target.setText(getCurrentTime()); + } + + public static void setCurrentDate(EditText target) { + target.setText(getCurrentDate()); + } + } diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/common/InfrastructureHelper.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/common/InfrastructureHelper.java index 79b0adf..8ee921d 100644 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/common/InfrastructureHelper.java +++ b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/common/InfrastructureHelper.java @@ -40,6 +40,10 @@ public static void showMessage(Context ctx, String msg) { Toast.makeText(ctx, msg, Toast.LENGTH_SHORT).show(); } + public static void showMessage(Context ctx, int resId) { + Toast.makeText(ctx, resId, Toast.LENGTH_SHORT).show(); + } + public static void logMethod(String tag, Object obj) { if (obj.getClass().isAnonymousClass()) { Log.d(tag, obj.getClass().getName() + " " + getCurrentMethodName()); @@ -48,6 +52,16 @@ public static void logMethod(String tag, Object obj) { } } + public static void logMethod(String tag, Object obj, String message) { + if (obj.getClass().isAnonymousClass()) { + Log.d(tag, obj.getClass().getName() + " " + getCurrentMethodName() + + ". Message: " + message); + } else { + Log.d(tag, obj.getClass().getSimpleName() + " " + getCurrentMethodName() + + ". Message: " + message); + } + } + public static void logMethod(String tag, Object obj, Object... args) { if (obj.getClass().isAnonymousClass()) { Log.d(tag, obj.getClass().getName() + " " + getCurrentMethodName() diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/eventbus/events/BaseIdEvent.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/eventbus/events/BaseIdEvent.java deleted file mode 100644 index 570618d..0000000 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/eventbus/events/BaseIdEvent.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.tom.meeter.infrastructure.eventbus.events; - -public class BaseIdEvent { - private final String id; - - public BaseIdEvent(String id) { - this.id = id; - } - - public String getId() { - return id; - } -} diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/eventbus/events/FailureEventCreation.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/eventbus/events/FailureEventCreation.java deleted file mode 100644 index e102bb4..0000000 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/eventbus/events/FailureEventCreation.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.tom.meeter.infrastructure.eventbus.events; - -public class FailureEventCreation { -} diff --git a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/eventbus/events/SuccessfulEventCreation.java b/AndroidClient/src/main/java/com/tom/meeter/infrastructure/eventbus/events/SuccessfulEventCreation.java deleted file mode 100644 index 9ce0fc9..0000000 --- a/AndroidClient/src/main/java/com/tom/meeter/infrastructure/eventbus/events/SuccessfulEventCreation.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.tom.meeter.infrastructure.eventbus.events; - -public class SuccessfulEventCreation extends BaseIdEvent { - - public SuccessfulEventCreation(String id) { - super(id); - } -} diff --git a/AndroidClient/src/main/res/layout/fragment_new_event.xml b/AndroidClient/src/main/res/layout/fragment_new_event.xml index 0e6e980..4693608 100644 --- a/AndroidClient/src/main/res/layout/fragment_new_event.xml +++ b/AndroidClient/src/main/res/layout/fragment_new_event.xml @@ -143,7 +143,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" - android:text="@string/other" + android:text="@string/map" android:textAllCaps="false" android:textSize="14sp" /> @@ -235,6 +235,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" + android:enabled="false" android:text="@string/now" android:textAllCaps="false" /> @@ -243,6 +244,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" + android:enabled="false" android:text="@string/other" android:textAllCaps="false" /> @@ -258,6 +260,7 @@ android:inputType="date" android:textAlignment="center" android:textSize="20sp" /> + @@ -331,17 +335,37 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" + android:enabled="false" android:text="@string/other" android:textAllCaps="false" /> + + + +