Browse Source

Merge pull request #2622 from nextcloud/feature/2369/localized-time-formatting

🕰️Localize time formatting
Andy Scherzinger 2 năm trước cách đây
mục cha
commit
b16a89349b
24 tập tin đã thay đổi với 175 bổ sung176 xóa
  1. 5 0
      app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingLinkPreviewMessageViewHolder.kt
  2. 6 0
      app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingLocationMessageViewHolder.kt
  3. 5 0
      app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingPollMessageViewHolder.kt
  4. 6 0
      app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingTextMessageViewHolder.kt
  5. 6 0
      app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingVoiceMessageViewHolder.kt
  6. 5 0
      app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingLinkPreviewMessageViewHolder.kt
  7. 5 0
      app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingLocationMessageViewHolder.kt
  8. 5 0
      app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingPollMessageViewHolder.kt
  9. 6 0
      app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingTextMessageViewHolder.kt
  10. 5 0
      app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingVoiceMessageViewHolder.kt
  11. 5 0
      app/src/main/java/com/nextcloud/talk/adapters/messages/PreviewMessageViewHolder.kt
  12. 8 0
      app/src/main/java/com/nextcloud/talk/adapters/messages/SystemMessageViewHolder.java
  13. 7 3
      app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt
  14. 5 2
      app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt
  15. 6 1
      app/src/main/java/com/nextcloud/talk/dagger/modules/RepositoryModule.kt
  16. 7 0
      app/src/main/java/com/nextcloud/talk/dagger/modules/UtilsModule.kt
  17. 5 0
      app/src/main/java/com/nextcloud/talk/remotefilebrowser/activities/RemoteFileBrowserActivity.kt
  18. 6 2
      app/src/main/java/com/nextcloud/talk/remotefilebrowser/adapters/RemoteFileBrowserItemsAdapter.kt
  19. 3 5
      app/src/main/java/com/nextcloud/talk/remotefilebrowser/adapters/RemoteFileBrowserItemsListViewHolder.kt
  20. 8 4
      app/src/main/java/com/nextcloud/talk/shareditems/repositories/SharedItemsRepositoryImpl.kt
  21. 37 17
      app/src/main/java/com/nextcloud/talk/utils/DateUtils.kt
  22. 0 1
      scripts/analysis/findbugs-results.txt
  23. 0 139
      scripts/analysis/findbugs-up.rb
  24. 24 2
      spotbugs-filter.xml

+ 5 - 0
app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingLinkPreviewMessageViewHolder.kt

@@ -40,6 +40,7 @@ import com.nextcloud.talk.models.json.chat.ChatMessage
 import com.nextcloud.talk.ui.recyclerview.MessageSwipeCallback
 import com.nextcloud.talk.ui.theme.ViewThemeUtils
 import com.nextcloud.talk.utils.ApiUtils
+import com.nextcloud.talk.utils.DateUtils
 import com.nextcloud.talk.utils.preferences.AppPreferences
 import com.stfalcon.chatkit.messages.MessageHolders
 import javax.inject.Inject
@@ -60,6 +61,9 @@ class IncomingLinkPreviewMessageViewHolder(incomingView: View, payload: Any) : M
     @Inject
     lateinit var viewThemeUtils: ViewThemeUtils
 
+    @Inject
+    lateinit var dateUtils: DateUtils
+
     @Inject
     lateinit var ncApi: NcApi
 
@@ -72,6 +76,7 @@ class IncomingLinkPreviewMessageViewHolder(incomingView: View, payload: Any) : M
         super.onBind(message)
         this.message = message
         sharedApplication!!.componentApplication.inject(this)
+        binding.messageTime.text = dateUtils.getLocalTimeStringFromTimestamp(message.timestamp)
 
         setAvatarAndAuthorOnMessageItem(message)
 

+ 6 - 0
app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingLocationMessageViewHolder.kt

@@ -49,6 +49,7 @@ import com.nextcloud.talk.extensions.loadChangelogBotAvatar
 import com.nextcloud.talk.models.json.chat.ChatMessage
 import com.nextcloud.talk.ui.theme.ViewThemeUtils
 import com.nextcloud.talk.utils.ApiUtils
+import com.nextcloud.talk.utils.DateUtils
 import com.nextcloud.talk.utils.UriUtils
 import com.nextcloud.talk.utils.preferences.AppPreferences
 import com.stfalcon.chatkit.messages.MessageHolders
@@ -75,6 +76,9 @@ class IncomingLocationMessageViewHolder(incomingView: View, payload: Any) : Mess
     @Inject
     lateinit var viewThemeUtils: ViewThemeUtils
 
+    @Inject
+    lateinit var dateUtils: DateUtils
+
     lateinit var commonMessageInterface: CommonMessageInterface
 
     @SuppressLint("SetTextI18n")
@@ -92,6 +96,8 @@ class IncomingLocationMessageViewHolder(incomingView: View, payload: Any) : Mess
         binding.messageText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize)
         binding.messageText.text = message.text
 
+        binding.messageTime.text = dateUtils.getLocalTimeStringFromTimestamp(message.timestamp)
+
         // parent message handling
         setParentMessageDataOnMessageItem(message)
 

+ 5 - 0
app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingPollMessageViewHolder.kt

@@ -39,6 +39,7 @@ import com.nextcloud.talk.models.json.chat.ChatMessage
 import com.nextcloud.talk.polls.ui.PollMainDialogFragment
 import com.nextcloud.talk.ui.theme.ViewThemeUtils
 import com.nextcloud.talk.utils.ApiUtils
+import com.nextcloud.talk.utils.DateUtils
 import com.nextcloud.talk.utils.preferences.AppPreferences
 import com.stfalcon.chatkit.messages.MessageHolders
 import javax.inject.Inject
@@ -59,6 +60,9 @@ class IncomingPollMessageViewHolder(incomingView: View, payload: Any) : MessageH
     @Inject
     lateinit var viewThemeUtils: ViewThemeUtils
 
+    @Inject
+    lateinit var dateUtils: DateUtils
+
     @Inject
     lateinit var ncApi: NcApi
 
@@ -71,6 +75,7 @@ class IncomingPollMessageViewHolder(incomingView: View, payload: Any) : MessageH
         super.onBind(message)
         this.message = message
         sharedApplication!!.componentApplication.inject(this)
+        binding.messageTime.text = dateUtils.getLocalTimeStringFromTimestamp(message.timestamp)
 
         setAvatarAndAuthorOnMessageItem(message)
 

+ 6 - 0
app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingTextMessageViewHolder.kt

@@ -45,6 +45,7 @@ import com.nextcloud.talk.models.json.chat.ChatMessage
 import com.nextcloud.talk.ui.recyclerview.MessageSwipeCallback
 import com.nextcloud.talk.ui.theme.ViewThemeUtils
 import com.nextcloud.talk.utils.ApiUtils
+import com.nextcloud.talk.utils.DateUtils
 import com.nextcloud.talk.utils.DisplayUtils
 import com.nextcloud.talk.utils.TextMatchers
 import com.nextcloud.talk.utils.preferences.AppPreferences
@@ -66,6 +67,9 @@ class IncomingTextMessageViewHolder(itemView: View, payload: Any) : MessageHolde
     @Inject
     lateinit var appPreferences: AppPreferences
 
+    @Inject
+    lateinit var dateUtils: DateUtils
+
     lateinit var commonMessageInterface: CommonMessageInterface
 
     override fun onBind(message: ChatMessage) {
@@ -104,6 +108,8 @@ class IncomingTextMessageViewHolder(itemView: View, payload: Any) : MessageHolde
         binding.messageText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize)
         binding.messageText.text = messageString
 
+        binding.messageTime.text = dateUtils.getLocalTimeStringFromTimestamp(message.timestamp)
+
         // parent message handling
         if (!message.isDeleted && message.parentMessage != null) {
             processParentMessage(message)

+ 6 - 0
app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingVoiceMessageViewHolder.kt

@@ -47,6 +47,7 @@ import com.nextcloud.talk.extensions.loadChangelogBotAvatar
 import com.nextcloud.talk.models.json.chat.ChatMessage
 import com.nextcloud.talk.ui.theme.ViewThemeUtils
 import com.nextcloud.talk.utils.ApiUtils
+import com.nextcloud.talk.utils.DateUtils
 import com.nextcloud.talk.utils.preferences.AppPreferences
 import com.stfalcon.chatkit.messages.MessageHolders
 import java.util.concurrent.ExecutionException
@@ -66,6 +67,9 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) : Message
     @Inject
     lateinit var viewThemeUtils: ViewThemeUtils
 
+    @Inject
+    lateinit var dateUtils: DateUtils
+
     @JvmField
     @Inject
     var appPreferences: AppPreferences? = null
@@ -81,6 +85,8 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) : Message
         this.message = message
         sharedApplication!!.componentApplication.inject(this)
 
+        binding.messageTime.text = dateUtils.getLocalTimeStringFromTimestamp(message.timestamp)
+
         setAvatarAndAuthorOnMessageItem(message)
 
         colorizeMessageBubble(message)

+ 5 - 0
app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingLinkPreviewMessageViewHolder.kt

@@ -39,6 +39,7 @@ import com.nextcloud.talk.models.json.chat.ReadStatus
 import com.nextcloud.talk.ui.recyclerview.MessageSwipeCallback
 import com.nextcloud.talk.ui.theme.ViewThemeUtils
 import com.nextcloud.talk.utils.ApiUtils
+import com.nextcloud.talk.utils.DateUtils
 import com.nextcloud.talk.utils.preferences.AppPreferences
 import com.stfalcon.chatkit.messages.MessageHolders
 import javax.inject.Inject
@@ -56,6 +57,9 @@ class OutcomingLinkPreviewMessageViewHolder(outcomingView: View, payload: Any) :
     @Inject
     lateinit var viewThemeUtils: ViewThemeUtils
 
+    @Inject
+    lateinit var dateUtils: DateUtils
+
     @Inject
     lateinit var appPreferences: AppPreferences
 
@@ -73,6 +77,7 @@ class OutcomingLinkPreviewMessageViewHolder(outcomingView: View, payload: Any) :
         sharedApplication!!.componentApplication.inject(this)
         val textColor = viewThemeUtils.getScheme(binding.messageTime.context).onSurfaceVariant
         binding.messageTime.setTextColor(textColor)
+        binding.messageTime.text = dateUtils.getLocalTimeStringFromTimestamp(message.timestamp)
 
         colorizeMessageBubble(message)
 

+ 5 - 0
app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingLocationMessageViewHolder.kt

@@ -46,6 +46,7 @@ import com.nextcloud.talk.models.json.chat.ChatMessage
 import com.nextcloud.talk.models.json.chat.ReadStatus
 import com.nextcloud.talk.ui.theme.ViewThemeUtils
 import com.nextcloud.talk.utils.ApiUtils
+import com.nextcloud.talk.utils.DateUtils
 import com.nextcloud.talk.utils.UriUtils
 import com.stfalcon.chatkit.messages.MessageHolders
 import java.net.URLEncoder
@@ -70,6 +71,9 @@ class OutcomingLocationMessageViewHolder(incomingView: View) : MessageHolders
     @Inject
     lateinit var viewThemeUtils: ViewThemeUtils
 
+    @Inject
+    lateinit var dateUtils: DateUtils
+
     lateinit var commonMessageInterface: CommonMessageInterface
 
     @SuppressLint("SetTextI18n")
@@ -78,6 +82,7 @@ class OutcomingLocationMessageViewHolder(incomingView: View) : MessageHolders
         sharedApplication!!.componentApplication.inject(this)
         val textColor = viewThemeUtils.getScheme(binding.messageTime.context).onSurfaceVariant
         binding.messageTime.setTextColor(textColor)
+        binding.messageTime.text = dateUtils.getLocalTimeStringFromTimestamp(message.timestamp)
 
         realView.isSelected = false
         val layoutParams = binding.messageTime.layoutParams as FlexboxLayout.LayoutParams

+ 5 - 0
app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingPollMessageViewHolder.kt

@@ -39,6 +39,7 @@ import com.nextcloud.talk.models.json.chat.ReadStatus
 import com.nextcloud.talk.polls.ui.PollMainDialogFragment
 import com.nextcloud.talk.ui.theme.ViewThemeUtils
 import com.nextcloud.talk.utils.ApiUtils
+import com.nextcloud.talk.utils.DateUtils
 import com.nextcloud.talk.utils.preferences.AppPreferences
 import com.stfalcon.chatkit.messages.MessageHolders
 import javax.inject.Inject
@@ -56,6 +57,9 @@ class OutcomingPollMessageViewHolder(outcomingView: View, payload: Any) : Messag
     @Inject
     lateinit var viewThemeUtils: ViewThemeUtils
 
+    @Inject
+    lateinit var dateUtils: DateUtils
+
     @Inject
     lateinit var appPreferences: AppPreferences
 
@@ -73,6 +77,7 @@ class OutcomingPollMessageViewHolder(outcomingView: View, payload: Any) : Messag
         sharedApplication!!.componentApplication.inject(this)
         val textColor = viewThemeUtils.getScheme(binding.messageTime.context).onSurfaceVariant
         binding.messageTime.setTextColor(textColor)
+        binding.messageTime.text = dateUtils.getLocalTimeStringFromTimestamp(message.timestamp)
 
         colorizeMessageBubble(message)
 

+ 6 - 0
app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingTextMessageViewHolder.kt

@@ -44,6 +44,7 @@ import com.nextcloud.talk.models.json.chat.ReadStatus
 import com.nextcloud.talk.ui.recyclerview.MessageSwipeCallback
 import com.nextcloud.talk.ui.theme.ViewThemeUtils
 import com.nextcloud.talk.utils.ApiUtils
+import com.nextcloud.talk.utils.DateUtils
 import com.nextcloud.talk.utils.DisplayUtils.searchAndReplaceWithMentionSpan
 import com.nextcloud.talk.utils.TextMatchers
 import com.stfalcon.chatkit.messages.MessageHolders.OutcomingTextMessageViewHolder
@@ -60,6 +61,9 @@ class OutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessageViewH
     @Inject
     lateinit var viewThemeUtils: ViewThemeUtils
 
+    @Inject
+    lateinit var dateUtils: DateUtils
+
     lateinit var commonMessageInterface: CommonMessageInterface
 
     override fun onBind(message: ChatMessage) {
@@ -88,6 +92,8 @@ class OutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessageViewH
         binding.messageText.setTextColor(textColor)
         binding.messageText.text = messageString
 
+        binding.messageTime.text = dateUtils.getLocalTimeStringFromTimestamp(message.timestamp)
+
         // parent message handling
         if (!message.isDeleted && message.parentMessage != null) {
             processParentMessage(message)

+ 5 - 0
app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingVoiceMessageViewHolder.kt

@@ -43,6 +43,7 @@ import com.nextcloud.talk.models.json.chat.ChatMessage
 import com.nextcloud.talk.models.json.chat.ReadStatus
 import com.nextcloud.talk.ui.theme.ViewThemeUtils
 import com.nextcloud.talk.utils.ApiUtils
+import com.nextcloud.talk.utils.DateUtils
 import com.nextcloud.talk.utils.preferences.AppPreferences
 import com.stfalcon.chatkit.messages.MessageHolders
 import java.util.concurrent.ExecutionException
@@ -62,6 +63,9 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) : MessageHolders
     @Inject
     lateinit var viewThemeUtils: ViewThemeUtils
 
+    @Inject
+    lateinit var dateUtils: DateUtils
+
     @JvmField
     @Inject
     var appPreferences: AppPreferences? = null
@@ -80,6 +84,7 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) : MessageHolders
         sharedApplication!!.componentApplication.inject(this)
         val textColor = viewThemeUtils.getScheme(binding.messageTime.context).onSurfaceVariant
         binding.messageTime.setTextColor(textColor)
+        binding.messageTime.text = dateUtils.getLocalTimeStringFromTimestamp(message.timestamp)
 
         colorizeMessageBubble(message)
 

+ 5 - 0
app/src/main/java/com/nextcloud/talk/adapters/messages/PreviewMessageViewHolder.kt

@@ -56,6 +56,7 @@ import com.nextcloud.talk.extensions.loadChangelogBotAvatar
 import com.nextcloud.talk.models.json.chat.ChatMessage
 import com.nextcloud.talk.ui.recyclerview.MessageSwipeCallback
 import com.nextcloud.talk.ui.theme.ViewThemeUtils
+import com.nextcloud.talk.utils.DateUtils
 import com.nextcloud.talk.utils.DisplayUtils
 import com.nextcloud.talk.utils.DrawableUtils.getDrawableResourceIdForMimeType
 import com.nextcloud.talk.utils.FileViewerUtils
@@ -81,6 +82,9 @@ abstract class PreviewMessageViewHolder(itemView: View?, payload: Any?) :
     @Inject
     var viewThemeUtils: ViewThemeUtils? = null
 
+    @Inject
+    lateinit var dateUtils: DateUtils
+
     @JvmField
     @Inject
     var okHttpClient: OkHttpClient? = null
@@ -102,6 +106,7 @@ abstract class PreviewMessageViewHolder(itemView: View?, payload: Any?) :
     @Suppress("NestedBlockDepth", "ComplexMethod", "LongMethod")
     override fun onBind(message: ChatMessage) {
         super.onBind(message)
+        time.text = dateUtils.getLocalTimeStringFromTimestamp(message.timestamp)
         if (userAvatar != null) {
             if (message.isGrouped || message.isOneToOneConversation) {
                 if (message.isOneToOneConversation) {

+ 8 - 0
app/src/main/java/com/nextcloud/talk/adapters/messages/SystemMessageViewHolder.java

@@ -31,6 +31,7 @@ import android.view.ViewGroup;
 import com.nextcloud.talk.R;
 import com.nextcloud.talk.application.NextcloudTalkApplication;
 import com.nextcloud.talk.models.json.chat.ChatMessage;
+import com.nextcloud.talk.utils.DateUtils;
 import com.nextcloud.talk.utils.DisplayUtils;
 import com.nextcloud.talk.utils.preferences.AppPreferences;
 import com.stfalcon.chatkit.messages.MessageHolders;
@@ -53,6 +54,9 @@ public class SystemMessageViewHolder extends MessageHolders.IncomingTextMessageV
     @Inject
     Context context;
 
+    @Inject
+    DateUtils dateUtils;
+
     protected ViewGroup background;
 
     public SystemMessageViewHolder(View itemView) {
@@ -101,6 +105,10 @@ public class SystemMessageViewHolder extends MessageHolders.IncomingTextMessageV
 
         text.setText(messageString);
 
+        if (time != null) {
+            time.setText(dateUtils.getLocalTimeStringFromTimestamp(message.getTimestamp()));
+        }
+
         itemView.setTag(REPLYABLE_VIEW_TAG, message.getReplyable());
     }
 }

+ 7 - 3
app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt

@@ -164,6 +164,7 @@ import com.nextcloud.talk.utils.ApiUtils
 import com.nextcloud.talk.utils.ConductorRemapping
 import com.nextcloud.talk.utils.ConductorRemapping.remapChatController
 import com.nextcloud.talk.utils.ContactUtils
+import com.nextcloud.talk.utils.DateConstants
 import com.nextcloud.talk.utils.DateUtils
 import com.nextcloud.talk.utils.FileUtils
 import com.nextcloud.talk.utils.ImageEmojiEditText
@@ -243,6 +244,9 @@ class ChatController(args: Bundle) :
     @Inject
     lateinit var permissionUtil: PlatformPermissionUtil
 
+    @Inject
+    lateinit var dateUtils: DateUtils
+
     val disposables = DisposableSet()
 
     var roomToken: String? = null
@@ -1348,12 +1352,12 @@ class ChatController(args: Bundle) :
                 if (currentConversation?.lobbyTimer != null && currentConversation?.lobbyTimer !=
                     0L
                 ) {
-                    val timestamp = currentConversation?.lobbyTimer ?: 0
+                    val timestampMS = (currentConversation?.lobbyTimer ?: 0) * DateConstants.SECOND_DIVIDER
                     val stringWithStartDate = String.format(
                         resources!!.getString(R.string.nc_lobby_start_date),
-                        DateUtils.getLocalDateStringFromTimestampForLobby(timestamp)
+                        dateUtils.getLocalDateTimeStringFromTimestamp(timestampMS)
                     )
-                    val relativeTime = DateUtils.relativeStartTimeForLobby(timestamp, resources!!)
+                    val relativeTime = dateUtils.relativeStartTimeForLobby(timestampMS, resources!!)
 
                     sb.append("$stringWithStartDate - $relativeTime")
                         .append("\n\n")

+ 5 - 2
app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt

@@ -118,6 +118,9 @@ class ConversationInfoController(args: Bundle) :
     @Inject
     lateinit var eventBus: EventBus
 
+    @Inject
+    lateinit var dateUtils: DateUtils
+
     private val conversationToken: String?
     private val conversationUser: User?
     private val hasAvatarSpacing: Boolean
@@ -311,8 +314,8 @@ class ConversationInfoController(args: Bundle) :
             conversation!!.lobbyTimer != 0L
         ) {
             binding.webinarInfoView.startTimePreferences.setSummary(
-                DateUtils.getLocalDateStringFromTimestampForLobby(
-                    conversation!!.lobbyTimer!!
+                dateUtils.getLocalDateTimeStringFromTimestamp(
+                    conversation!!.lobbyTimer!! * DateConstants.SECOND_DIVIDER,
                 )
             )
         } else {

+ 6 - 1
app/src/main/java/com/nextcloud/talk/dagger/modules/RepositoryModule.kt

@@ -43,14 +43,19 @@ import com.nextcloud.talk.repositories.unifiedsearch.UnifiedSearchRepository
 import com.nextcloud.talk.repositories.unifiedsearch.UnifiedSearchRepositoryImpl
 import com.nextcloud.talk.shareditems.repositories.SharedItemsRepository
 import com.nextcloud.talk.shareditems.repositories.SharedItemsRepositoryImpl
+import com.nextcloud.talk.utils.DateUtils
 import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew
 import dagger.Module
 import dagger.Provides
 import okhttp3.OkHttpClient
+import javax.inject.Inject
 
 @Module
 class RepositoryModule {
 
+    @Inject
+    lateinit var dateUtils: DateUtils
+
     @Provides
     fun provideConversationsRepository(ncApi: NcApi, userProvider: CurrentUserProviderNew): ConversationsRepository {
         return ConversationsRepositoryImpl(ncApi, userProvider)
@@ -58,7 +63,7 @@ class RepositoryModule {
 
     @Provides
     fun provideSharedItemsRepository(ncApi: NcApi): SharedItemsRepository {
-        return SharedItemsRepositoryImpl(ncApi)
+        return SharedItemsRepositoryImpl(ncApi, dateUtils)
     }
 
     @Provides

+ 7 - 0
app/src/main/java/com/nextcloud/talk/dagger/modules/UtilsModule.kt

@@ -22,6 +22,7 @@
 package com.nextcloud.talk.dagger.modules
 
 import android.content.Context
+import com.nextcloud.talk.utils.DateUtils
 import com.nextcloud.talk.utils.permissions.PlatformPermissionUtil
 import com.nextcloud.talk.utils.permissions.PlatformPermissionUtilImpl
 import dagger.Module
@@ -35,4 +36,10 @@ class UtilsModule {
     fun providePermissionUtil(context: Context): PlatformPermissionUtil {
         return PlatformPermissionUtilImpl(context)
     }
+
+    @Provides
+    @Reusable
+    fun provideDateUtils(context: Context): DateUtils {
+        return DateUtils(context)
+    }
 }

+ 5 - 0
app/src/main/java/com/nextcloud/talk/remotefilebrowser/activities/RemoteFileBrowserActivity.kt

@@ -46,6 +46,7 @@ import com.nextcloud.talk.remotefilebrowser.adapters.RemoteFileBrowserItemsAdapt
 import com.nextcloud.talk.remotefilebrowser.viewmodels.RemoteFileBrowserItemsViewModel
 import com.nextcloud.talk.ui.dialog.SortingOrderDialogFragment
 import com.nextcloud.talk.ui.theme.ViewThemeUtils
+import com.nextcloud.talk.utils.DateUtils
 import com.nextcloud.talk.utils.DisplayUtils
 import com.nextcloud.talk.utils.FileSortOrder
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_MIME_TYPE_FILTER
@@ -64,6 +65,9 @@ class RemoteFileBrowserActivity : AppCompatActivity(), SelectionInterface, Swipe
     @Inject
     lateinit var viewThemeUtils: ViewThemeUtils
 
+    @Inject
+    lateinit var dateUtils: DateUtils
+
     private lateinit var binding: ActivityRemoteFileBrowserBinding
     private lateinit var viewModel: RemoteFileBrowserItemsViewModel
 
@@ -169,6 +173,7 @@ class RemoteFileBrowserActivity : AppCompatActivity(), SelectionInterface, Swipe
             user = currentUserProvider.currentUser.blockingGet(),
             selectionInterface = this,
             viewThemeUtils = viewThemeUtils,
+            dateUtils = dateUtils,
             onItemClicked = viewModel::onItemClicked
         )
         adapter.items = remoteFileBrowserItems

+ 6 - 2
app/src/main/java/com/nextcloud/talk/remotefilebrowser/adapters/RemoteFileBrowserItemsAdapter.kt

@@ -29,6 +29,7 @@ import com.nextcloud.talk.databinding.RvItemBrowserFileBinding
 import com.nextcloud.talk.remotefilebrowser.SelectionInterface
 import com.nextcloud.talk.remotefilebrowser.model.RemoteFileBrowserItem
 import com.nextcloud.talk.ui.theme.ViewThemeUtils
+import com.nextcloud.talk.utils.DateUtils
 
 class RemoteFileBrowserItemsAdapter(
     private val showGrid: Boolean = false,
@@ -36,6 +37,7 @@ class RemoteFileBrowserItemsAdapter(
     private val user: User,
     private val selectionInterface: SelectionInterface,
     private val viewThemeUtils: ViewThemeUtils,
+    private val dateUtils: DateUtils,
     private val onItemClicked: (RemoteFileBrowserItem) -> Unit
 ) : RecyclerView.Adapter<RemoteFileBrowserItemsViewHolder>() {
 
@@ -52,7 +54,8 @@ class RemoteFileBrowserItemsAdapter(
                 mimeTypeSelectionFilter,
                 user,
                 selectionInterface,
-                viewThemeUtils
+                viewThemeUtils,
+                dateUtils
             ) {
                 onItemClicked(items[it])
             }
@@ -66,7 +69,8 @@ class RemoteFileBrowserItemsAdapter(
                 mimeTypeSelectionFilter,
                 user,
                 selectionInterface,
-                viewThemeUtils
+                viewThemeUtils,
+                dateUtils
             ) {
                 onItemClicked(items[it])
             }

+ 3 - 5
app/src/main/java/com/nextcloud/talk/remotefilebrowser/adapters/RemoteFileBrowserItemsListViewHolder.kt

@@ -23,9 +23,7 @@ package com.nextcloud.talk.remotefilebrowser.adapters
 import android.text.format.Formatter
 import android.view.View
 import android.widget.ImageView
-import autodagger.AutoInjector
 import com.nextcloud.talk.R
-import com.nextcloud.talk.application.NextcloudTalkApplication
 import com.nextcloud.talk.data.user.model.User
 import com.nextcloud.talk.databinding.RvItemBrowserFileBinding
 import com.nextcloud.talk.extensions.loadImage
@@ -33,16 +31,16 @@ import com.nextcloud.talk.remotefilebrowser.SelectionInterface
 import com.nextcloud.talk.remotefilebrowser.model.RemoteFileBrowserItem
 import com.nextcloud.talk.ui.theme.ViewThemeUtils
 import com.nextcloud.talk.utils.ApiUtils
-import com.nextcloud.talk.utils.DateUtils.getLocalDateTimeStringFromTimestamp
+import com.nextcloud.talk.utils.DateUtils
 import com.nextcloud.talk.utils.Mimetype.FOLDER
 
-@AutoInjector(NextcloudTalkApplication::class)
 class RemoteFileBrowserItemsListViewHolder(
     override val binding: RvItemBrowserFileBinding,
     mimeTypeSelectionFilter: String?,
     currentUser: User,
     selectionInterface: SelectionInterface,
     private val viewThemeUtils: ViewThemeUtils,
+    private val dateUtils: DateUtils,
     onItemClicked: (Int) -> Unit
 ) : RemoteFileBrowserItemsViewHolder(binding, mimeTypeSelectionFilter, currentUser, selectionInterface) {
 
@@ -111,7 +109,7 @@ class RemoteFileBrowserItemsListViewHolder(
         binding.fileModifiedInfo.text = String.format(
             binding.fileModifiedInfo.context.getString(R.string.nc_last_modified),
             Formatter.formatShortFileSize(binding.fileModifiedInfo.context, item.size),
-            getLocalDateTimeStringFromTimestamp(item.modifiedTimestamp)
+            dateUtils.getLocalDateTimeStringFromTimestamp(item.modifiedTimestamp)
         )
 
         binding.selectFileCheckbox.isChecked = selectionInterface.isPathSelected(item.path!!)

+ 8 - 4
app/src/main/java/com/nextcloud/talk/shareditems/repositories/SharedItemsRepositoryImpl.kt

@@ -37,6 +37,7 @@ import com.nextcloud.talk.shareditems.model.SharedLocationItem
 import com.nextcloud.talk.shareditems.model.SharedOtherItem
 import com.nextcloud.talk.shareditems.model.SharedPollItem
 import com.nextcloud.talk.utils.ApiUtils
+import com.nextcloud.talk.utils.DateConstants
 import com.nextcloud.talk.utils.DateUtils
 import io.reactivex.Observable
 import retrofit2.Response
@@ -44,7 +45,8 @@ import java.util.HashMap
 import java.util.Locale
 import javax.inject.Inject
 
-class SharedItemsRepositoryImpl @Inject constructor(private val ncApi: NcApi) : SharedItemsRepository {
+class SharedItemsRepositoryImpl @Inject constructor(private val ncApi: NcApi, private val dateUtils: DateUtils) :
+    SharedItemsRepository {
 
     override fun media(
         parameters: SharedItemsRepository.Parameters,
@@ -86,8 +88,8 @@ class SharedItemsRepositoryImpl @Inject constructor(private val ncApi: NcApi) :
         if (mediaItems != null) {
             for (it in mediaItems) {
                 val actorParameters = it.value.messageParameters!!["actor"]!!
-                val dateTime = DateUtils.getLocalDateTimeStringFromTimestamp(
-                    it.value.timestamp * ONE_SECOND_IN_MILLIS
+                val dateTime = dateUtils.getLocalDateTimeStringFromTimestamp(
+                    it.value.timestamp * DateConstants.SECOND_DIVIDER
                 )
 
                 if (it.value.messageParameters?.containsKey("file") == true) {
@@ -145,6 +147,7 @@ class SharedItemsRepositoryImpl @Inject constructor(private val ncApi: NcApi) :
                     dateTime
                 )
             }
+
             "geo-location" -> {
                 returnValue = SharedLocationItem(
                     objectParameters["id"]!!,
@@ -155,6 +158,7 @@ class SharedItemsRepositoryImpl @Inject constructor(private val ncApi: NcApi) :
                     Uri.parse(objectParameters["id"]!!.replace("geo:", "geo:0,0?z=11&q="))
                 )
             }
+
             "deck-card" -> {
                 returnValue = SharedDeckCardItem(
                     objectParameters["id"]!!,
@@ -165,6 +169,7 @@ class SharedItemsRepositoryImpl @Inject constructor(private val ncApi: NcApi) :
                     Uri.parse(objectParameters["link"]!!)
                 )
             }
+
             else -> {
                 returnValue = SharedOtherItem(
                     objectParameters["id"]!!,
@@ -212,7 +217,6 @@ class SharedItemsRepositoryImpl @Inject constructor(private val ncApi: NcApi) :
 
     companion object {
         const val BATCH_SIZE: Int = 28
-        private const val ONE_SECOND_IN_MILLIS = 1000
         private val TAG = SharedItemsRepositoryImpl::class.simpleName
     }
 }

+ 37 - 17
app/src/main/java/com/nextcloud/talk/utils/DateUtils.kt

@@ -20,6 +20,7 @@
 
 package com.nextcloud.talk.utils
 
+import android.content.Context
 import android.content.res.Resources
 import android.icu.text.RelativeDateTimeFormatter
 import android.icu.text.RelativeDateTimeFormatter.Direction
@@ -29,36 +30,52 @@ import com.nextcloud.talk.R
 import java.text.DateFormat
 import java.util.Calendar
 import java.util.Date
-import java.util.Locale
 import kotlin.math.roundToInt
 
-object DateUtils {
+class DateUtils(val context: Context) {
+    private val cal = Calendar.getInstance()
+    private val tz = cal.timeZone
 
-    private const val TIMESTAMP_CORRECTION_MULTIPLIER = 1000
+    /* date formatter in local timezone and locale */
+    private var format: DateFormat = DateFormat.getDateTimeInstance(
+        DateFormat.DEFAULT, // dateStyle
+        DateFormat.SHORT, // timeStyle
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+            context.resources.configuration.locales[0]
+        } else {
+            @Suppress("DEPRECATION")
+            context.resources.configuration.locale
+        },
+    )
 
-    fun getLocalDateTimeStringFromTimestamp(timestamp: Long): String {
-        val cal = Calendar.getInstance()
-        val tz = cal.timeZone
+    /* date formatter in local timezone and locale */
+    private var formatTime: DateFormat = DateFormat.getTimeInstance(
+        DateFormat.SHORT, // timeStyle
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+            context.resources.configuration.locales[0]
+        } else {
+            @Suppress("DEPRECATION")
+            context.resources.configuration.locale
+        },
+    )
 
-        /* date formatter in local timezone */
-        val format = DateFormat.getDateTimeInstance(
-            DateFormat.DEFAULT, DateFormat.SHORT,
-            Locale.getDefault()
-        )
+    init {
         format.timeZone = tz
-
-        return format.format(Date(timestamp))
+        formatTime.timeZone = tz
     }
 
-    fun getLocalDateStringFromTimestampForLobby(timestamp: Long): String {
-        return getLocalDateTimeStringFromTimestamp(timestamp * TIMESTAMP_CORRECTION_MULTIPLIER)
+    fun getLocalDateTimeStringFromTimestamp(timestampMilliseconds: Long): String {
+        return format.format(Date(timestampMilliseconds))
     }
 
-    fun relativeStartTimeForLobby(timestamp: Long, resources: Resources): String {
+    fun getLocalTimeStringFromTimestamp(timestampSeconds: Long): String {
+        return formatTime.format(Date(timestampSeconds * DateConstants.SECOND_DIVIDER))
+    }
 
+    fun relativeStartTimeForLobby(timestampMilliseconds: Long, resources: Resources): String {
         return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
             val fmt = RelativeDateTimeFormatter.getInstance()
-            val timeLeftMillis = timestamp * TIMESTAMP_CORRECTION_MULTIPLIER - System.currentTimeMillis()
+            val timeLeftMillis = timestampMilliseconds - System.currentTimeMillis()
             val minutes = timeLeftMillis.toDouble() / DateConstants.SECOND_DIVIDER / DateConstants.MINUTES_DIVIDER
             val hours = minutes / DateConstants.HOURS_DIVIDER
             val days = hours / DateConstants.DAYS_DIVIDER
@@ -75,6 +92,7 @@ object DateUtils {
                         RelativeUnit.DAYS
                     )
                 }
+
                 hoursInt > 0 -> {
                     fmt.format(
                         hoursInt.toDouble(),
@@ -82,6 +100,7 @@ object DateUtils {
                         RelativeUnit.HOURS
                     )
                 }
+
                 minutesInt > 1 -> {
                     fmt.format(
                         minutesInt.toDouble(),
@@ -89,6 +108,7 @@ object DateUtils {
                         RelativeUnit.MINUTES
                     )
                 }
+
                 else -> {
                     resources.getString(R.string.nc_lobby_start_soon)
                 }

+ 0 - 1
scripts/analysis/findbugs-results.txt

@@ -1 +0,0 @@
-136

+ 0 - 139
scripts/analysis/findbugs-up.rb

@@ -1,139 +0,0 @@
-## Script from https://github.com/tir38/android-lint-entropy-reducer at 07.05.2017
-# adapts to drone, use git username / token as parameter
-
-Encoding.default_external = Encoding::UTF_8
-Encoding.default_internal = Encoding::UTF_8
-
-puts "=================== starting Android FindBugs Entropy Reducer ===================="
-
-# get args
-git_user, git_token, git_branch = ARGV
-
-# ========================  SETUP ============================
-
-# User name for git commits made by this script.
-TRAVIS_GIT_USERNAME = String.new("Drone CI server")
-
-# File name and relative path of generated FindBugs report. Must match build.gradle file:
-#   lintOptions {
-#       htmlOutput file("[FILE_NAME].html")
-#   }
-FINDBUGS_REPORT_FILE = String.new("app/build/reports/spotbugs/spotbugs.html")
-
-# File name and relative path of previous results of this script.
-PREVIOUS_FINDBUGS_RESULTS_FILE=String.new("scripts/analysis/findbugs-results.txt")
-
-# Flag to evaluate warnings. true = check warnings; false = ignore warnings
-CHECK_WARNINGS = true
-
-# File name and relative path to custom FindBugs rules; Can be null or "".
-CUSTOM_FINDBUGS_FILE = String.new("")
-
-# ================ SETUP DONE; DON'T TOUCH ANYTHING BELOW  ================
-
-require 'fileutils'
-require 'pathname'
-require 'open3'
-
-# since we need the xml-simple gem, and we want this script self-contained, let's grab it just when we need it
-begin
-    gem "xml-simple"
-    rescue LoadError
-    system("gem install --user-install xml-simple")
-    Gem.clear_paths
-end
-
-require 'xmlsimple'
-
-# run FindBugs
-puts "running FindBugs..."
-system './gradlew --console=plain assembleGplayDebug 1>/dev/null'
-
-# confirm that assemble ran w/out error
-result = $?.to_i
-if result != 0
-    puts "FAIL: failed to run ./gradlew --console=plain assembleGplayDebug"
-    exit 1
-end
-
-system './gradlew --console=plain spotbugsGplayDebugReport 1>/dev/null 2>&1'
-
-# find FindBugs report file
-findbugs_reports = Dir.glob(FINDBUGS_REPORT_FILE)
-if findbugs_reports.length == 0
-    puts "Findbugs HTML report not found."
-    exit 1
-end
-findbugs_report = String.new(findbugs_reports[0])
-
-# find number of warnings
-current_warning_count = `grep -A 3 "<b>Total</b>" app/build/reports/spotbugs/spotbugs.html | tail -n1 | cut -f2 -d">" | cut -f1 -d"<"`.to_i
-puts "found warnings: " + current_warning_count.to_s
-
-# get warning counts from last successful build
-
-previous_results = false
-
-previous_findbugs_reports = Dir.glob(PREVIOUS_FINDBUGS_RESULTS_FILE)
-if previous_findbugs_reports.nil? || previous_findbugs_reports.length == 0
-    previous_findbugs_report = File.new(PREVIOUS_FINDBUGS_RESULTS_FILE, "w") # create for writing to later
-else
-    previous_findbugs_report = String.new(previous_findbugs_reports[0])
-
-    previous_warning_count = File.open(previous_findbugs_report, &:readline).match(/[0-9]*/)[0].to_i
-
-    if previous_warning_count.nil?
-        previous_results = false
-    else
-        previous_results = true
-
-        puts "previous warnings: " + previous_warning_count.to_s
-    end
-end
-
-# compare previous warning count with current warning count
-if previous_results == true && current_warning_count > previous_warning_count
-    puts "FAIL: warning count increased"
-    exit 1
-end
-
-# check if warning and error count stayed the same
-if  previous_results == true && current_warning_count == previous_warning_count
-    puts "SUCCESS: count stayed the same"
-    exit 2
-end
-
-# warning count DECREASED
-puts "SUCCESS: count decreased from " + previous_warning_count.to_s + " to " + current_warning_count.to_s
-
-# write new results to file (will overwrite existing, or create new)
-File.write(previous_findbugs_report, current_warning_count)
-
-# push changes to github (if this script is run locally, we don't want to overwrite git username and email, so save temporarily)
-previous_git_username, _ = Open3.capture2('git config user.name')
-previous_git_username = previous_git_username.strip
-
-previous_git_email, _ = Open3.capture3('git config user.email')
-previous_git_email = previous_git_email.strip
-
-# update git user name and email for this script
-system ("git config --local user.name '"  + git_user + "'")
-system ("git config --local user.email 'android@nextcloud.com'")
-system ("git remote rm origin")
-system ("git remote add origin https://" + git_user + ":" + git_token + "@github.com/nextcloud/talk-android")
-
-# add previous FindBugs result file to git
-system ('git add ' + PREVIOUS_FINDBUGS_RESULTS_FILE)
-
-# commit changes; Add "skip ci" so that we don't accidentally trigger another Drone build
-system({"GIT_COMMITTER_EMAIL" => "drone@nextcloud.com", "GIT_AUTHOR_EMAIL" => "drone@nextcloud.com"}, 'git commit -sm "Drone: update FindBugs results to reflect reduced error/warning count [skip ci]"')
-
-# push to origin
-system ('git push origin HEAD:' + git_branch)
-
-# restore previous git user name and email
-system("git config --local user.name '#{previous_git_username}'")
-system("git config --local user.email '#{previous_git_email}'")
-
-puts "SUCCESS: count was reduced"
-exit 0 # success

+ 24 - 2
spotbugs-filter.xml

@@ -54,12 +54,16 @@
     <Match>
         <Or>
             <Class name="~.*\.Dagger.*" />
-			<Class name="~dagger\.android\..*" />
+			<Class name="~~.*\.dagger\.android\..*" />
+			<Class name="~~.*\.dagger\.modules\..*" />
         </Or>
     </Match>
     <!-- Dagger generated code uses internal APIs -->
     <Match>
-        <Class name="~.*\..*.*Factory" />
+	    <Or>
+            <Class name="~.*\..*.*Factory" />
+		    <Class name="~.*\..*.*Factory_Impl" />
+		</Or>
         <Bug pattern="IICU_INCORRECT_INTERNAL_CLASS_USE" />
     </Match>
 
@@ -76,12 +80,30 @@
     <Match>
         <Class name="~.*\$\$JsonObjectMapper.*" />
     </Match>
+    
+	<!-- Third-party library code -->
+	<Match>
+	    <Or>
+            <Package name="~third\.parties\..*" />
+		</Or>
+	</Match>    
 
     <Bug pattern="PATH_TRAVERSAL_IN" />
     <Bug pattern="ANDROID_EXTERNAL_FILE_ACCESS" />
     <Bug pattern="BAS_BLOATED_ASSIGNMENT_SCOPE" />
     <Bug pattern="IMC_IMMATURE_CLASS_BAD_SERIALVERSIONUID" />
+    <Bug pattern="EI_EXPOSE_REP" />
+    <Bug pattern="EI_EXPOSE_REP2" />
 
     <!-- This is unmanageable for now due to large amount of interconnected static state -->
     <Bug pattern="FCCD_FIND_CLASS_CIRCULAR_DEPENDENCY" />
+
+    <!--Autogenerated Room classes-->
+    <Match>
+        <Class name="~.*\.TalkDatabase_Impl.*" />
+    </Match>
+    <Match>
+        <Class name="~.*\..*Dao_Impl.*" />
+    </Match>
+
 </FindBugsFilter>