diff --git a/.github/workflows/analysis.yml b/.github/workflows/analysis.yml index 36332b85f..6faea7699 100644 --- a/.github/workflows/analysis.yml +++ b/.github/workflows/analysis.yml @@ -1,53 +1,54 @@ +# synced from @nextcloud/android-config name: "Analysis" on: - pull_request: - branches: [ master, stable-* ] - push: - branches: [ master, stable-* ] + pull_request: + branches: [ "master", "main", "stable-*" ] + push: + branches: [ "master", "main", "stable-*" ] permissions: - pull-requests: write - contents: write + pull-requests: write + contents: write concurrency: - group: analysis-wrapper-${{ github.head_ref || github.run_id }} - cancel-in-progress: true + group: analysis-wrapper-${{ github.head_ref || github.run_id }} + cancel-in-progress: true jobs: - analysis: - runs-on: ubuntu-latest - steps: - - name: Setup variables - id: get-vars - run: | - if [ -z "$GITHUB_HEAD_REF" ]; then - # push - echo "branch=$GITHUB_REF_NAME" >> "$GITHUB_OUTPUT" - echo "pr=$GITHUB_RUN_ID" >> "$GITHUB_OUTPUT" - echo "repo=${{ github.repository }}" >> "$GITHUB_OUTPUT" - else - # pull request - echo "branch=$GITHUB_HEAD_REF" >> "$GITHUB_OUTPUT" - echo "pr=${{ github.event.pull_request.number }}" >> "$GITHUB_OUTPUT" - echo "repo=${{ github.event.pull_request.head.repo.full_name }}" >> "$GITHUB_OUTPUT" - fi - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - with: - repository: ${{ steps.get-vars.outputs.repo }} - ref: ${{ steps.get-vars.outputs.branch }} - - name: Set up JDK 17 - uses: actions/setup-java@cd89f46ac9d01407894225f350157564c9c7cee2 # v3.12.0 - with: - distribution: "temurin" - java-version: 17 - - name: Install dependencies - run: | - python3 -m pip install defusedxml - - name: Run analysis wrapper - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - mkdir -p $HOME/.gradle - echo "org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError" > $HOME/.gradle/gradle.properties - scripts/analysis/analysis-wrapper.sh ${{ steps.get-vars.outputs.branch }} ${{ secrets.LOG_USERNAME }} ${{ secrets.LOG_PASSWORD }} $GITHUB_RUN_NUMBER ${{ steps.get-vars.outputs.pr }} + analysis: + runs-on: ubuntu-latest + steps: + - name: Setup variables + id: get-vars + run: | + if [ -z "$GITHUB_HEAD_REF" ]; then + # push + echo "branch=$GITHUB_REF_NAME" >> "$GITHUB_OUTPUT" + echo "pr=$GITHUB_RUN_ID" >> "$GITHUB_OUTPUT" + echo "repo=${{ github.repository }}" >> "$GITHUB_OUTPUT" + else + # pull request + echo "branch=$GITHUB_HEAD_REF" >> "$GITHUB_OUTPUT" + echo "pr=${{ github.event.pull_request.number }}" >> "$GITHUB_OUTPUT" + echo "repo=${{ github.event.pull_request.head.repo.full_name }}" >> "$GITHUB_OUTPUT" + fi + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + with: + repository: ${{ steps.get-vars.outputs.repo }} + ref: ${{ steps.get-vars.outputs.branch }} + - name: Set up JDK 17 + uses: actions/setup-java@cd89f46ac9d01407894225f350157564c9c7cee2 # v3.12.0 + with: + distribution: "temurin" + java-version: 17 + - name: Install dependencies + run: | + python3 -m pip install defusedxml + - name: Run analysis wrapper + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + mkdir -p $HOME/.gradle + echo "org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError" > $HOME/.gradle/gradle.properties + scripts/analysis/analysis-wrapper.sh ${{ steps.get-vars.outputs.branch }} ${{ secrets.LOG_USERNAME }} ${{ secrets.LOG_PASSWORD }} $GITHUB_RUN_NUMBER ${{ steps.get-vars.outputs.pr }} diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index cdabd8752..38a7a6855 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -32,7 +32,7 @@ jobs: with: swap-size-gb: 10 - name: Initialize CodeQL - uses: github/codeql-action/init@0ba4244466797eb048eb91a6cd43d5c03ca8bd05 # v2.21.2 + uses: github/codeql-action/init@a09933a12a80f87b87005513f0abb1494c27a716 # v2.21.4 with: languages: ${{ matrix.language }} - name: Set up JDK 17 @@ -46,4 +46,4 @@ jobs: echo "org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError" > "$HOME/.gradle/gradle.properties" ./gradlew assembleDebug - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@0ba4244466797eb048eb91a6cd43d5c03ca8bd05 # v2.21.2 + uses: github/codeql-action/analyze@a09933a12a80f87b87005513f0abb1494c27a716 # v2.21.4 diff --git a/.github/workflows/pr-feedback.yml b/.github/workflows/pr-feedback.yml index d63b5656e..559e183f3 100644 --- a/.github/workflows/pr-feedback.yml +++ b/.github/workflows/pr-feedback.yml @@ -1,3 +1,8 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization + name: 'Ask for feedback on PRs' on: schedule: @@ -5,7 +10,7 @@ on: jobs: pr-feedback: - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest steps: - name: The get-github-handles-from-website action uses: marcelklehr/get-github-handles-from-website-action@a739600f6b91da4957f51db0792697afbb2f143c # v1.0.0 @@ -25,5 +30,5 @@ jobs: Thank you for contributing to Nextcloud and we hope to hear from you soon! days-before-feedback: 14 start-date: "2023-07-10" - exempt-authors: "${{ steps.scrape.outputs.users }}" + exempt-authors: "${{ steps.scrape.outputs.users }},nextcloud-command,nextcloud-android-bot" exempt-bots: true diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 48a69dddc..c0a2f471e 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -37,6 +37,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@0ba4244466797eb048eb91a6cd43d5c03ca8bd05 # v2.21.2 + uses: github/codeql-action/upload-sarif@a09933a12a80f87b87005513f0abb1494c27a716 # v2.21.4 with: sarif_file: results.sarif diff --git a/app/build.gradle b/app/build.gradle index e44739b47..49ed55530 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -46,8 +46,8 @@ android { // mayor.minor.hotfix.increment (for increment: 01-50=Alpha / 51-89=RC / 90-99=stable) // xx .xxx .xx .xx - versionCode 170100014 - versionName "17.10.0 Alpha 14" + versionCode 170100016 + versionName "17.10.0 Alpha 16" flavorDimensions "default" renderscriptTargetApi 19 @@ -162,7 +162,7 @@ configurations.all { } dependencies { - implementation 'androidx.preference:preference-ktx:1.2.0' + implementation 'androidx.preference:preference-ktx:1.2.1' detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:1.23.1") implementation fileTree(include: ['*'], dir: 'libs') diff --git a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.kt b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.kt index 5c574a4c4..13d25556a 100644 --- a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.kt @@ -1083,13 +1083,11 @@ class CallActivity : CallBaseActivity() { } private fun getSpotlightView(): SpotlightView? { - val primary = viewThemeUtils.getScheme(binding!!.audioOutputButton.context).primary - return SpotlightView.Builder(this) + val builder = SpotlightView.Builder(this) .introAnimationDuration(300) .enableRevealAnimation(true) .performClick(false) .fadeinTextDuration(400) - .headingTvColor(primary) .headingTvSize(20) .headingTvText(resources.getString(R.string.nc_push_to_talk)) .subHeadingTvColor(resources.getColor(R.color.bg_default, null)) @@ -1098,11 +1096,11 @@ class CallActivity : CallBaseActivity() { .maskColor(Color.parseColor("#dc000000")) .target(binding!!.microphoneButton) .lineAnimDuration(400) - .lineAndArcColor(primary) .enableDismissAfterShown(true) .dismissOnBackPress(true) .usageId("pushToTalk") - .show() + + return viewThemeUtils.talk.themeSpotlightView(context, builder).show() } private fun onCameraClick() { diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/AdvancedUserItem.java b/app/src/main/java/com/nextcloud/talk/adapters/items/AdvancedUserItem.java index bb82cfa26..494918d39 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/items/AdvancedUserItem.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/items/AdvancedUserItem.java @@ -41,7 +41,6 @@ import androidx.annotation.Nullable; import eu.davidea.flexibleadapter.FlexibleAdapter; import eu.davidea.flexibleadapter.items.AbstractFlexibleItem; import eu.davidea.flexibleadapter.items.IFilterable; -import eu.davidea.flexibleadapter.utils.FlexibleUtils; import eu.davidea.viewholders.FlexibleViewHolder; public class AdvancedUserItem extends AbstractFlexibleItem implements @@ -65,8 +64,7 @@ public class AdvancedUserItem extends AbstractFlexibleItem implements @@ -74,8 +73,7 @@ public class ContactItem extends AbstractFlexibleItem implements IFilterable { @@ -103,8 +102,7 @@ public class MentionAutocompleteItem extends AbstractFlexibleItem implements @@ -81,8 +80,7 @@ public class ParticipantItem extends AbstractFlexibleItem context?.resources?.getString(R.string.nc_message_read) - ReadStatus.SENT -> context?.resources?.getString(R.string.nc_message_sent) + ReadStatus.READ -> context.resources?.getString(R.string.nc_message_read) + ReadStatus.SENT -> context.resources?.getString(R.string.nc_message_sent) else -> null } readStatusDrawableInt?.let { drawableInt -> AppCompatResources.getDrawable(context, drawableInt)?.let { binding.checkMark.setImageDrawable(it) - binding.checkMark.setColorFilter( - viewThemeUtils.getScheme(binding.checkMark.context).onSurfaceVariant, - PorterDuff.Mode.SRC_ATOP - ) + viewThemeUtils.talk.themeMessageCheckMark(binding.checkMark) } } @@ -176,7 +173,8 @@ class OutcomingLinkPreviewMessageViewHolder(outcomingView: View, payload: Any) : .enrichChatReplyMessageText( binding.messageQuote.quotedMessage.context, parentChatMessage, - viewThemeUtils.getScheme(binding.messageQuote.quotedMessage.context).onSurfaceVariant + false, + viewThemeUtils ) viewThemeUtils.talk.colorOutgoingQuoteText(binding.messageQuote.quotedMessage) viewThemeUtils.talk.colorOutgoingQuoteAuthorText(binding.messageQuote.quotedMessageAuthor) diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingLocationMessageViewHolder.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingLocationMessageViewHolder.kt index 8e15e3133..1684d1b59 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingLocationMessageViewHolder.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingLocationMessageViewHolder.kt @@ -25,7 +25,6 @@ package com.nextcloud.talk.adapters.messages import android.annotation.SuppressLint import android.content.Context import android.content.Intent -import android.graphics.PorterDuff import android.net.Uri import android.util.Log import android.util.TypedValue @@ -84,15 +83,14 @@ class OutcomingLocationMessageViewHolder(incomingView: View) : override fun onBind(message: ChatMessage) { super.onBind(message) sharedApplication!!.componentApplication.inject(this) - val textColor = viewThemeUtils.getScheme(binding.messageTime.context).onSurfaceVariant - binding.messageTime.setTextColor(textColor) + viewThemeUtils.platform.colorTextView(binding.messageTime, ColorRole.ON_SURFACE_VARIANT) binding.messageTime.text = dateUtils.getLocalTimeStringFromTimestamp(message.timestamp) realView.isSelected = false val layoutParams = binding.messageTime.layoutParams as FlexboxLayout.LayoutParams layoutParams.isWrapBefore = false - val textSize = context!!.resources.getDimension(R.dimen.chat_text_size) + val textSize = context.resources.getDimension(R.dimen.chat_text_size) colorizeMessageBubble(message) binding.messageText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize) @@ -110,22 +108,19 @@ class OutcomingLocationMessageViewHolder(incomingView: View) : } val readStatusContentDescriptionString = when (message.readStatus) { - ReadStatus.READ -> context?.resources?.getString(R.string.nc_message_read) - ReadStatus.SENT -> context?.resources?.getString(R.string.nc_message_sent) + ReadStatus.READ -> context.resources?.getString(R.string.nc_message_read) + ReadStatus.SENT -> context.resources?.getString(R.string.nc_message_sent) else -> null } readStatusDrawableInt?.let { drawableInt -> - AppCompatResources.getDrawable(context!!, drawableInt)?.let { + AppCompatResources.getDrawable(context, drawableInt)?.let { binding.checkMark.setImageDrawable(it) - binding.checkMark.setColorFilter( - viewThemeUtils.getScheme(binding.checkMark.context).onSurfaceVariant, - PorterDuff.Mode.SRC_ATOP - ) + viewThemeUtils.talk.themeMessageCheckMark(binding.checkMark) } } - binding.checkMark.setContentDescription(readStatusContentDescriptionString) + binding.checkMark.contentDescription = readStatusContentDescriptionString // geo-location setLocationDataOnMessageItem(message) @@ -163,7 +158,7 @@ class OutcomingLocationMessageViewHolder(incomingView: View) : } } - binding.webview.settings?.javaScriptEnabled = true + binding.webview.settings.javaScriptEnabled = true binding.webview.webViewClient = object : WebViewClient() { @Deprecated("Use shouldOverrideUrlLoading(WebView view, WebResourceRequest request)") @@ -180,11 +175,11 @@ class OutcomingLocationMessageViewHolder(incomingView: View) : val urlStringBuffer = StringBuffer("file:///android_asset/leafletMapMessagePreview.html") urlStringBuffer.append( - "?mapProviderUrl=" + URLEncoder.encode(context!!.getString(R.string.osm_tile_server_url)) + "?mapProviderUrl=" + URLEncoder.encode(context.getString(R.string.osm_tile_server_url)) ) urlStringBuffer.append( "&mapProviderAttribution=" + URLEncoder.encode( - context!!.getString( + context.getString( R.string .osm_tile_server_attributation ) @@ -224,12 +219,13 @@ class OutcomingLocationMessageViewHolder(incomingView: View) : binding.messageQuote.quotedMessageImage.visibility = View.GONE } binding.messageQuote.quotedMessageAuthor.text = parentChatMessage.actorDisplayName - ?: context!!.getText(R.string.nc_nick_guest) + ?: context.getText(R.string.nc_nick_guest) binding.messageQuote.quotedMessage.text = messageUtils .enrichChatReplyMessageText( binding.messageQuote.quotedMessage.context, parentChatMessage, - viewThemeUtils.getScheme(binding.messageQuote.quotedMessage.context).onSurfaceVariant + false, + viewThemeUtils ) viewThemeUtils.talk.colorOutgoingQuoteText(binding.messageQuote.quotedMessage) viewThemeUtils.talk.colorOutgoingQuoteAuthorText(binding.messageQuote.quotedMessageAuthor) @@ -250,7 +246,7 @@ class OutcomingLocationMessageViewHolder(incomingView: View) : val geoLinkWithMarker = addMarkerToGeoLink(locationGeoLink!!) val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(geoLinkWithMarker)) browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - context!!.startActivity(browserIntent) + context.startActivity(browserIntent) } else { Snackbar.make(binding.root, R.string.nc_common_error_sorry, Snackbar.LENGTH_LONG).show() Log.e(TAG, "locationGeoLink was null or empty") diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingPollMessageViewHolder.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingPollMessageViewHolder.kt index 7c12298aa..f850c82de 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingPollMessageViewHolder.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingPollMessageViewHolder.kt @@ -23,11 +23,11 @@ package com.nextcloud.talk.adapters.messages import android.annotation.SuppressLint import android.content.Context -import android.graphics.PorterDuff import android.view.View import androidx.appcompat.content.res.AppCompatResources import autodagger.AutoInjector import coil.load +import com.nextcloud.android.common.ui.theme.utils.ColorRole import com.nextcloud.talk.R import com.nextcloud.talk.api.NcApi import com.nextcloud.talk.application.NextcloudTalkApplication @@ -78,8 +78,7 @@ class OutcomingPollMessageViewHolder(outcomingView: View, payload: Any) : super.onBind(message) this.message = message sharedApplication!!.componentApplication.inject(this) - val textColor = viewThemeUtils.getScheme(binding.messageTime.context).onSurfaceVariant - binding.messageTime.setTextColor(textColor) + viewThemeUtils.platform.colorTextView(binding.messageTime, ColorRole.ON_SURFACE_VARIANT) binding.messageTime.text = dateUtils.getLocalTimeStringFromTimestamp(message.timestamp) colorizeMessageBubble(message) @@ -96,18 +95,15 @@ class OutcomingPollMessageViewHolder(outcomingView: View, payload: Any) : } val readStatusContentDescriptionString = when (message.readStatus) { - ReadStatus.READ -> context?.resources?.getString(R.string.nc_message_read) - ReadStatus.SENT -> context?.resources?.getString(R.string.nc_message_sent) + ReadStatus.READ -> context.resources?.getString(R.string.nc_message_read) + ReadStatus.SENT -> context.resources?.getString(R.string.nc_message_sent) else -> null } readStatusDrawableInt?.let { drawableInt -> AppCompatResources.getDrawable(context, drawableInt)?.let { binding.checkMark.setImageDrawable(it) - binding.checkMark.setColorFilter( - viewThemeUtils.getScheme(binding.checkMark.context).onSurfaceVariant, - PorterDuff.Mode.SRC_ATOP - ) + viewThemeUtils.talk.themeMessageCheckMark(binding.checkMark) } } @@ -191,7 +187,8 @@ class OutcomingPollMessageViewHolder(outcomingView: View, payload: Any) : .enrichChatReplyMessageText( binding.messageQuote.quotedMessage.context, parentChatMessage, - viewThemeUtils.getScheme(binding.messageQuote.quotedMessage.context).onSurfaceVariant + false, + viewThemeUtils ) viewThemeUtils.talk.colorOutgoingQuoteText(binding.messageQuote.quotedMessage) viewThemeUtils.talk.colorOutgoingQuoteAuthorText(binding.messageQuote.quotedMessageAuthor) diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingTextMessageViewHolder.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingTextMessageViewHolder.kt index 3931f810a..680af44a6 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingTextMessageViewHolder.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingTextMessageViewHolder.kt @@ -24,13 +24,13 @@ package com.nextcloud.talk.adapters.messages import android.content.Context -import android.graphics.PorterDuff import android.util.TypedValue import android.view.View import androidx.core.content.res.ResourcesCompat import autodagger.AutoInjector import coil.load import com.google.android.flexbox.FlexboxLayout +import com.nextcloud.android.common.ui.theme.utils.ColorRole import com.nextcloud.talk.R import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication @@ -71,11 +71,14 @@ class OutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessageViewH realView.isSelected = false val layoutParams = binding.messageTime.layoutParams as FlexboxLayout.LayoutParams layoutParams.isWrapBefore = false - var textSize = context!!.resources.getDimension(R.dimen.chat_text_size) - val textColor = viewThemeUtils.getScheme(binding.messageText.context).onSurfaceVariant - binding.messageTime.setTextColor(textColor) - - var processedMessageText = messageUtils.enrichChatMessageText(binding.messageText.context, message, textColor) + var textSize = context.resources.getDimension(R.dimen.chat_text_size) + viewThemeUtils.platform.colorTextView(binding.messageTime, ColorRole.ON_SURFACE_VARIANT) + var processedMessageText = messageUtils.enrichChatMessageText( + binding.messageText.context, + message, + false, + viewThemeUtils + ) processedMessageText = messageUtils.processMessageParameters( binding.messageText.context, viewThemeUtils, @@ -98,7 +101,7 @@ class OutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessageViewH binding.messageText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize) binding.messageTime.layoutParams = layoutParams - binding.messageText.setTextColor(textColor) + viewThemeUtils.platform.colorTextView(binding.messageText, ColorRole.ON_SURFACE_VARIANT) binding.messageText.text = processedMessageText binding.messageTime.text = dateUtils.getLocalTimeStringFromTimestamp(message.timestamp) @@ -118,22 +121,19 @@ class OutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessageViewH } val readStatusContentDescriptionString = when (message.readStatus) { - ReadStatus.READ -> context?.resources?.getString(R.string.nc_message_read) - ReadStatus.SENT -> context?.resources?.getString(R.string.nc_message_sent) + ReadStatus.READ -> context.resources?.getString(R.string.nc_message_read) + ReadStatus.SENT -> context.resources?.getString(R.string.nc_message_sent) else -> null } readStatusDrawableInt?.let { drawableInt -> - ResourcesCompat.getDrawable(context!!.resources, drawableInt, null)?.let { + ResourcesCompat.getDrawable(context.resources, drawableInt, null)?.let { binding.checkMark.setImageDrawable(it) - binding.checkMark.setColorFilter( - viewThemeUtils.getScheme(binding.messageText.context).onSurfaceVariant, - PorterDuff.Mode.SRC_ATOP - ) + viewThemeUtils.talk.themeMessageCheckMark(binding.checkMark) } } - binding.checkMark.setContentDescription(readStatusContentDescriptionString) + binding.checkMark.contentDescription = readStatusContentDescriptionString itemView.setTag(R.string.replyable_message_view_tag, message.replyable) @@ -158,7 +158,6 @@ class OutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessageViewH private fun processParentMessage(message: ChatMessage) { val parentChatMessage = message.parentMessage - val textColor = viewThemeUtils.getScheme(binding.messageQuote.quotedMessage.context).onSurfaceVariant parentChatMessage!!.activeUser = message.activeUser parentChatMessage.imageUrl?.let { binding.messageQuote.quotedMessageImage.visibility = View.VISIBLE @@ -172,19 +171,20 @@ class OutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessageViewH binding.messageQuote.quotedMessageImage.visibility = View.GONE } binding.messageQuote.quotedMessageAuthor.text = parentChatMessage.actorDisplayName - ?: context!!.getText(R.string.nc_nick_guest) + ?: context.getText(R.string.nc_nick_guest) binding.messageQuote.quotedMessage.text = messageUtils .enrichChatReplyMessageText( binding.messageQuote.quotedMessage.context, parentChatMessage, - textColor + false, + viewThemeUtils ) - binding.messageQuote.quotedMessageAuthor.setTextColor(textColor) - binding.messageQuote.quotedMessage.setTextColor(textColor) - binding.messageQuote.quoteColoredView.setBackgroundColor(textColor) + viewThemeUtils.talk.colorOutgoingQuoteText(binding.messageQuote.quotedMessage) + viewThemeUtils.talk.colorOutgoingQuoteAuthorText(binding.messageQuote.quotedMessageAuthor) + viewThemeUtils.talk.colorOutgoingQuoteBackground(binding.messageQuote.quoteColoredView) - binding.messageQuote.quotedChatMessageView.setOnClickListener() { + binding.messageQuote.quotedChatMessageView.setOnClickListener { val chatActivity = commonMessageInterface as ChatActivity chatActivity.jumpToQuotedMessage(parentChatMessage) } diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingVoiceMessageViewHolder.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingVoiceMessageViewHolder.kt index ea6d1114a..2fe5ff6af 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingVoiceMessageViewHolder.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingVoiceMessageViewHolder.kt @@ -24,7 +24,6 @@ package com.nextcloud.talk.adapters.messages import android.annotation.SuppressLint import android.content.Context -import android.graphics.PorterDuff import android.os.Handler import android.util.Log import android.view.View @@ -86,8 +85,7 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) : super.onBind(message) this.message = message sharedApplication!!.componentApplication.inject(this) - val textColor = viewThemeUtils.getScheme(binding.messageTime.context).onSurfaceVariant - binding.messageTime.setTextColor(textColor) + viewThemeUtils.platform.colorTextView(binding.messageTime, ColorRole.ON_SURFACE_VARIANT) binding.messageTime.text = dateUtils.getLocalTimeStringFromTimestamp(message.timestamp) colorizeMessageBubble(message) @@ -139,10 +137,7 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) : readStatusDrawableInt?.let { drawableInt -> AppCompatResources.getDrawable(context!!, drawableInt)?.let { binding.checkMark.setImageDrawable(it) - binding.checkMark.setColorFilter( - viewThemeUtils.getScheme(binding.checkMark.context).onSurfaceVariant, - PorterDuff.Mode.SRC_ATOP - ) + viewThemeUtils.talk.themeMessageCheckMark(binding.checkMark) } } @@ -291,7 +286,8 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) : .enrichChatReplyMessageText( binding.messageQuote.quotedMessage.context, parentChatMessage, - viewThemeUtils.getScheme(binding.messageQuote.quotedMessage.context).onSurfaceVariant + false, + viewThemeUtils ) viewThemeUtils.talk.colorOutgoingQuoteText(binding.messageQuote.quotedMessage) viewThemeUtils.talk.colorOutgoingQuoteAuthorText(binding.messageQuote.quotedMessageAuthor) diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/PreviewMessageViewHolder.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/PreviewMessageViewHolder.kt index 47f71972c..7b1ef8fc8 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/PreviewMessageViewHolder.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/PreviewMessageViewHolder.kt @@ -28,7 +28,6 @@ package com.nextcloud.talk.adapters.messages import android.annotation.SuppressLint import android.content.Context import android.content.Intent -import android.graphics.PorterDuff import android.graphics.drawable.Drawable import android.net.Uri import android.os.Handler @@ -235,17 +234,14 @@ abstract class PreviewMessageViewHolder(itemView: View?, payload: Any?) : if (message.selectedIndividualHashMap!!.containsKey(KEY_MIMETYPE)) { val mimetype = message.selectedIndividualHashMap!![KEY_MIMETYPE] val drawableResourceId = getDrawableResourceIdForMimeType(mimetype) - val drawable = ContextCompat.getDrawable(context!!, drawableResourceId) + var drawable = ContextCompat.getDrawable(context!!, drawableResourceId) if (drawable != null && ( drawableResourceId == R.drawable.ic_mimetype_folder || drawableResourceId == R.drawable.ic_mimetype_package_x_generic ) ) { - drawable.setColorFilter( - viewThemeUtils!!.getScheme(image.context).primary, - PorterDuff.Mode.SRC_ATOP - ) + drawable = viewThemeUtils?.platform?.tintDrawable(context!!, drawable) } placeholder = drawable } else { diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/Reaction.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/Reaction.kt index 73586d9a3..2e38b9bb3 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/Reaction.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/Reaction.kt @@ -25,8 +25,6 @@ import android.view.View import android.view.ViewGroup import android.widget.LinearLayout import android.widget.TextView -import androidx.core.content.ContextCompat -import com.nextcloud.talk.R import com.nextcloud.talk.databinding.ReactionsInsideMessageBinding import com.nextcloud.talk.models.json.chat.ChatMessage import com.nextcloud.talk.ui.theme.ViewThemeUtils @@ -65,7 +63,7 @@ class Reaction { val isSelfReaction = message.reactionsSelf != null && message.reactionsSelf!!.isNotEmpty() && message.reactionsSelf!!.contains(emoji) - val textColor = getTextColor(isOutgoingMessage, isSelfReaction, binding, viewThemeUtils) + val textColor = viewThemeUtils.talk.getTextColor(isOutgoingMessage, isSelfReaction, binding) val emojiWithAmountWrapper = getEmojiWithAmountWrapperLayout( binding.reactionsEmojiWrapper.context, emoji, @@ -112,15 +110,7 @@ class Reaction { emojiWithAmountWrapper.layoutParams = layoutInfo.wrapperParams if (layoutInfo.isSelfReaction) { - val color = if (layoutInfo.isOutgoingMessage) { - ContextCompat.getColor( - emojiWithAmountWrapper.context, - R.color.bg_message_list_incoming_bubble - ) - } else { - layoutInfo.viewThemeUtils.getScheme(emojiWithAmountWrapper.context).primaryContainer - } - layoutInfo.viewThemeUtils.talk.setCheckedBackground(emojiWithAmountWrapper, color) + layoutInfo.viewThemeUtils.talk.setCheckedBackground(emojiWithAmountWrapper, layoutInfo.isOutgoingMessage) emojiWithAmountWrapper.setPaddingRelative( layoutInfo.paddingSide, @@ -176,19 +166,6 @@ class Reaction { return amountParams } - private fun getTextColor( - isOutgoingMessage: Boolean, - isSelfReaction: Boolean, - binding: ReactionsInsideMessageBinding, - viewThemeUtils: ViewThemeUtils - ): Int { - var textColor = viewThemeUtils.getScheme(binding.root.context).onSurfaceVariant - if (!isOutgoingMessage || isSelfReaction) { - textColor = ContextCompat.getColor(binding.root.context, R.color.high_emphasis_text) - } - return textColor - } - private data class EmojiWithAmountWrapperLayoutInfo( val textColor: Int, val amountParams: LinearLayout.LayoutParams, diff --git a/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt b/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt index 79c001132..4486144e3 100644 --- a/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt @@ -1618,9 +1618,10 @@ class ChatActivity : currentConversation!!.status, null, size, - viewThemeUtils.platform.getScheme(binding.chatToolbar.context).surface, + 0, binding.chatToolbar.context ) + viewThemeUtils.talk.themeStatusDrawable(context, status) binding.chatToolbar.findViewById(R.id.chat_toolbar_avatar) .setImageDrawable(BitmapDrawable(resources, bitmap)) binding.chatToolbar.findViewById(R.id.chat_toolbar_status) diff --git a/app/src/main/java/com/nextcloud/talk/remotefilebrowser/activities/RemoteFileBrowserActivity.kt b/app/src/main/java/com/nextcloud/talk/remotefilebrowser/activities/RemoteFileBrowserActivity.kt index f1647ffc4..ec0ee64fd 100644 --- a/app/src/main/java/com/nextcloud/talk/remotefilebrowser/activities/RemoteFileBrowserActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/remotefilebrowser/activities/RemoteFileBrowserActivity.kt @@ -26,7 +26,6 @@ package com.nextcloud.talk.remotefilebrowser.activities import android.app.Activity import android.content.Intent -import android.content.res.ColorStateList import android.os.Bundle import android.util.Log import android.view.Menu @@ -90,13 +89,10 @@ class RemoteFileBrowserActivity : AppCompatActivity(), SelectionInterface, Swipe binding = ActivityRemoteFileBrowserBinding.inflate(layoutInflater) setSupportActionBar(binding.remoteFileBrowserItemsToolbar) viewThemeUtils.material.themeToolbar(binding.remoteFileBrowserItemsToolbar) - val scheme = viewThemeUtils.getScheme(binding.sortListButtonGroup.context) - binding.sortListButtonGroup.setBackgroundColor(scheme.surface) - binding.sortButton.iconTint = ColorStateList.valueOf(scheme.onSurface) - binding.sortButton.setTextColor(scheme.onSurface) + viewThemeUtils.talk.themeSortListButtonGroup(binding.sortListButtonGroup) + viewThemeUtils.talk.themeSortButton(binding.sortButton) viewThemeUtils.material.colorMaterialTextButton(binding.sortButton) - binding.pathNavigationBackButton.iconTint = ColorStateList.valueOf(scheme.onSurface) - binding.pathNavigationBackButton.setTextColor(scheme.onSurface) + viewThemeUtils.talk.themePathNavigationButton(binding.pathNavigationBackButton) viewThemeUtils.material.colorMaterialTextButton(binding.pathNavigationBackButton) viewThemeUtils.platform.themeStatusBar(this) setContentView(binding.root) @@ -199,7 +195,7 @@ class RemoteFileBrowserActivity : AppCompatActivity(), SelectionInterface, Swipe override fun onCreateOptionsMenu(menu: Menu): Boolean { super.onCreateOptionsMenu(menu) menuInflater.inflate(R.menu.menu_share_files, menu) - filesSelectionDoneMenuItem = menu?.findItem(R.id.files_selection_done) + filesSelectionDoneMenuItem = menu.findItem(R.id.files_selection_done) return true } diff --git a/app/src/main/java/com/nextcloud/talk/ui/StatusDrawable.java b/app/src/main/java/com/nextcloud/talk/ui/StatusDrawable.java index b2a1fe1b8..2505c98d3 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/StatusDrawable.java +++ b/app/src/main/java/com/nextcloud/talk/ui/StatusDrawable.java @@ -33,6 +33,7 @@ import android.text.TextUtils; import com.nextcloud.talk.R; +import androidx.annotation.ColorInt; import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.core.content.res.ResourcesCompat; @@ -44,11 +45,17 @@ public class StatusDrawable extends Drawable { private String text; private StatusDrawableType icon = StatusDrawableType.UNDEFINED; private Paint textPaint; - private final int backgroundColor; + private int backgroundColor; private final float radius; private Context context; - public StatusDrawable(String status, String statusIcon, float statusSize, int backgroundColor, Context context) { + public void colorStatusDrawable(@ColorInt int color) { + backgroundColor = color; + invalidateSelf(); + } + + public StatusDrawable(String status, String statusIcon, float statusSize, int backgroundColor, + Context context) { radius = statusSize; this.backgroundColor = backgroundColor; @@ -58,19 +65,17 @@ public class StatusDrawable extends Drawable { this.context = context; } else if (TextUtils.isEmpty(statusIcon) && status != null) { switch (status) { - case "online": + case "online" -> { icon = StatusDrawableType.ONLINE; this.context = context; - break; - - case "away": + } + case "away" -> { icon = StatusDrawableType.AWAY; this.context = context; - break; - - default: - // do not show - break; + } + default -> { + } + // do not show } } else { text = statusIcon; diff --git a/app/src/main/java/com/nextcloud/talk/ui/dialog/ChooseAccountDialogFragment.java b/app/src/main/java/com/nextcloud/talk/ui/dialog/ChooseAccountDialogFragment.java index 57fe1d61d..1e2c37cf6 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/dialog/ChooseAccountDialogFragment.java +++ b/app/src/main/java/com/nextcloud/talk/ui/dialog/ChooseAccountDialogFragment.java @@ -329,12 +329,14 @@ public class ChooseAccountDialogFragment extends DialogFragment { private void drawStatus() { float size = DisplayUtils.convertDpToPixel(STATUS_SIZE_IN_DP, getContext()); binding.currentAccount.ticker.setBackground(null); - binding.currentAccount.ticker.setImageDrawable(new StatusDrawable( + StatusDrawable drawable = new StatusDrawable( status.getStatus(), status.getIcon(), size, - viewThemeUtils.getScheme(binding.currentAccount.ticker.getContext()).getSurface(), - getContext())); + 0, + getContext()); + viewThemeUtils.talk.themeStatusDrawable(binding.currentAccount.ticker.getContext(), drawable); + binding.currentAccount.ticker.setImageDrawable(drawable); binding.currentAccount.ticker.setVisibility(View.VISIBLE); diff --git a/app/src/main/java/com/nextcloud/talk/ui/theme/TalkSpecificViewThemeUtils.kt b/app/src/main/java/com/nextcloud/talk/ui/theme/TalkSpecificViewThemeUtils.kt index 99fb803c7..5a06acef8 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/theme/TalkSpecificViewThemeUtils.kt +++ b/app/src/main/java/com/nextcloud/talk/ui/theme/TalkSpecificViewThemeUtils.kt @@ -26,13 +26,19 @@ import android.content.Context import android.content.res.ColorStateList import android.graphics.PorterDuff import android.graphics.PorterDuffColorFilter +import android.graphics.Typeface import android.graphics.drawable.Drawable import android.graphics.drawable.LayerDrawable import android.os.Build +import android.text.Spannable +import android.text.Spanned +import android.text.style.ForegroundColorSpan +import android.text.style.StyleSpan import android.view.View +import android.widget.ImageView import android.widget.LinearLayout +import android.widget.RelativeLayout import android.widget.TextView -import androidx.annotation.ColorInt import androidx.annotation.DrawableRes import androidx.appcompat.content.res.AppCompatResources import androidx.appcompat.widget.SearchView @@ -42,17 +48,23 @@ import androidx.core.content.res.ResourcesCompat import androidx.core.graphics.ColorUtils import androidx.core.graphics.drawable.DrawableCompat import androidx.core.view.ViewCompat +import com.google.android.material.button.MaterialButton import com.google.android.material.card.MaterialCardView import com.google.android.material.materialswitch.MaterialSwitch import com.nextcloud.android.common.ui.theme.MaterialSchemes import com.nextcloud.android.common.ui.theme.ViewThemeUtilsBase import com.nextcloud.android.common.ui.theme.utils.AndroidXViewThemeUtils import com.nextcloud.talk.R +import com.nextcloud.talk.databinding.ReactionsInsideMessageBinding import com.nextcloud.talk.ui.MicInputCloud +import com.nextcloud.talk.ui.StatusDrawable import com.nextcloud.talk.ui.WaveformSeekBar import com.nextcloud.talk.utils.DisplayUtils import com.nextcloud.talk.utils.DrawableUtils +import com.nextcloud.talk.utils.message.MessageUtils import com.vanniktech.emoji.EmojiTextView +import com.wooplr.spotlight.SpotlightView +import eu.davidea.flexibleadapter.utils.FlexibleUtils import javax.inject.Inject import kotlin.math.roundToInt @@ -160,11 +172,19 @@ class TalkSpecificViewThemeUtils @Inject constructor( } } - fun setCheckedBackground(linearLayout: LinearLayout, @ColorInt backgroundColor: Int) { + fun setCheckedBackground(linearLayout: LinearLayout, incoming: Boolean) { withScheme(linearLayout) { scheme -> val drawable = AppCompatResources .getDrawable(linearLayout.context, R.drawable.reaction_self_background)!! .mutate() + val backgroundColor = if (incoming) { + scheme.primaryContainer + } else { + ContextCompat.getColor( + linearLayout.context, + R.color.bg_message_list_incoming_bubble + ) + } DrawableCompat.setTintList( drawable, ColorStateList.valueOf(backgroundColor) @@ -263,6 +283,111 @@ class TalkSpecificViewThemeUtils @Inject constructor( } } + fun themeForegroundColorSpan(context: Context): ForegroundColorSpan { + return withScheme(context) { scheme -> + return@withScheme ForegroundColorSpan(scheme.primary) + } + } + + fun themeSpotlightView(context: Context, builder: SpotlightView.Builder): SpotlightView.Builder { + return withScheme(context) { scheme -> + return@withScheme builder.headingTvColor(scheme.primary).lineAndArcColor(scheme.primary) + } + } + + fun themeAndHighlightText( + textView: TextView, + originalText: String?, + c: String? + ) { + withScheme(textView) { scheme -> + var constraint = c + constraint = FlexibleUtils.toLowerCase(constraint) + var start = FlexibleUtils.toLowerCase(originalText).indexOf(constraint) + if (start != -1) { + val spanText = Spannable.Factory.getInstance().newSpannable(originalText) + do { + val end = start + constraint.length + spanText.setSpan( + ForegroundColorSpan(scheme.primary), + start, + end, + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE + ) + spanText.setSpan(StyleSpan(Typeface.BOLD), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) + start = FlexibleUtils.toLowerCase(originalText) + .indexOf(constraint, end + 1) // +1 skips the consecutive span + } while (start != -1) + textView.setText(spanText, TextView.BufferType.SPANNABLE) + } else { + textView.setText(originalText, TextView.BufferType.NORMAL) + } + } + } + + fun themeSortButton(sortButton: MaterialButton) { + withScheme(sortButton) { scheme -> + sortButton.iconTint = ColorStateList.valueOf(scheme.onSurface) + sortButton.setTextColor(scheme.onSurface) + } + } + + fun themePathNavigationButton(navigationBtn: MaterialButton) { + withScheme(navigationBtn) { scheme -> + navigationBtn.iconTint = ColorStateList.valueOf(scheme.onSurface) + navigationBtn.setTextColor(scheme.onSurface) + } + } + + fun themeSortListButtonGroup(relativeLayout: RelativeLayout) { + withScheme(relativeLayout) { scheme -> + relativeLayout.setBackgroundColor(scheme.surface) + } + } + + fun themeStatusDrawable(context: Context, statusDrawable: StatusDrawable) { + withScheme(context) { scheme -> + statusDrawable.colorStatusDrawable(scheme.surface) + } + } + + fun themeMessageCheckMark(imageView: ImageView) { + withScheme(imageView) { scheme -> + imageView.setColorFilter( + scheme.onSurfaceVariant, + PorterDuff.Mode.SRC_ATOP + ) + } + } + + fun themeMarkdown(context: Context, message: String, incoming: Boolean): Spanned { + return withScheme(context) { scheme -> + return@withScheme if (incoming) { + MessageUtils(context).getRenderedMarkdownText( + context, + message, + context.getColor(R.color.nc_incoming_text_default) + ) + } else { + MessageUtils(context).getRenderedMarkdownText(context, message, scheme.onSurfaceVariant) + } + } + } + + fun getTextColor( + isOutgoingMessage: Boolean, + isSelfReaction: Boolean, + binding: ReactionsInsideMessageBinding + ): Int { + return withScheme(binding.root) { scheme -> + return@withScheme if (!isOutgoingMessage || isSelfReaction) { + ContextCompat.getColor(binding.root.context, R.color.high_emphasis_text) + } else { + scheme.onSurfaceVariant + } + } + } + companion object { private val THEMEABLE_PLACEHOLDER_IDS = listOf( R.drawable.ic_mimetype_package_x_generic, diff --git a/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java b/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java index dc681d951..4682f50fc 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java +++ b/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java @@ -292,7 +292,7 @@ public class DisplayUtils { if (chipXmlRes == R.xml.chip_you) { spannableString.setSpan( - new ForegroundColorSpan(viewThemeUtils.getScheme(context).getOnPrimary()), + viewThemeUtils.talk.themeForegroundColorSpan(context), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); diff --git a/app/src/main/java/com/nextcloud/talk/utils/message/MessageUtils.kt b/app/src/main/java/com/nextcloud/talk/utils/message/MessageUtils.kt index 19df56225..89b64c55f 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/message/MessageUtils.kt +++ b/app/src/main/java/com/nextcloud/talk/utils/message/MessageUtils.kt @@ -40,28 +40,48 @@ import io.noties.markwon.ext.tasklist.TaskListDrawable import io.noties.markwon.ext.tasklist.TaskListPlugin class MessageUtils(val context: Context) { - fun enrichChatReplyMessageText(context: Context, message: ChatMessage, textColor: Int): Spanned? { + fun enrichChatReplyMessageText( + context: Context, + message: ChatMessage, + incoming: Boolean, + viewThemeUtils: ViewThemeUtils + ): Spanned? { return if (message.message == null) { null } else if (message.renderMarkdown == false) { - SpannableString(DisplayUtils.ellipsize(message.message!!, MAX_REPLY_LENGTH)) + SpannableString(DisplayUtils.ellipsize(message.text, MAX_REPLY_LENGTH)) } else { - enrichChatMessageText(context, DisplayUtils.ellipsize(message.message!!, MAX_REPLY_LENGTH), textColor) + enrichChatMessageText( + context, + DisplayUtils.ellipsize(message.text, MAX_REPLY_LENGTH), + incoming, + viewThemeUtils + ) } } - fun enrichChatMessageText(context: Context, message: ChatMessage, textColor: Int): Spanned? { + fun enrichChatMessageText( + context: Context, + message: ChatMessage, + incoming: Boolean, + viewThemeUtils: ViewThemeUtils + ): Spanned? { return if (message.message == null) { null } else if (message.renderMarkdown == false) { SpannableString(message.message) } else { - enrichChatMessageText(context, message.message!!, textColor) + enrichChatMessageText(context, message.message!!, incoming, viewThemeUtils) } } - private fun enrichChatMessageText(context: Context, message: String, textColor: Int): Spanned { - return getRenderedMarkdownText(context, message, textColor) + private fun enrichChatMessageText( + context: Context, + message: String, + incoming: Boolean, + viewThemeUtils: ViewThemeUtils + ): Spanned { + return viewThemeUtils.talk.themeMarkdown(context, message, incoming) } fun processMessageParameters( @@ -131,7 +151,7 @@ class MessageUtils(val context: Context) { return messageStringInternal } - private fun getRenderedMarkdownText(context: Context, markdown: String, textColor: Int): Spanned { + fun getRenderedMarkdownText(context: Context, markdown: String, textColor: Int): Spanned { val drawable = TaskListDrawable(textColor, textColor, context.getColor(R.color.bg_default)) val markwon = Markwon.builder(context).usePlugin(object : AbstractMarkwonPlugin() { override fun configureTheme(builder: MarkwonTheme.Builder) { diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index 16d818646..2f9a17045 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -10,6 +10,7 @@ Avatar Absent Opcions avançades de trucada + La trucada porta una hora en marxa. Trucada sense notificació S\'ha concedit el permís de càmera. Torneu a triar la càmera. Trieu un avatar del núvol @@ -334,6 +335,7 @@ tema Clar Tema + Comparteix el meu estat d\'escriptura i mostra l\'estat d\'escriptura dels altres El proxy necessita credencials Avís Només el compte actual pot ser re-autoritzat @@ -455,6 +457,7 @@ Adjunts Avui Traducció + Copia el text traduït Detectar idioma Paràmetres del dispositiu No s\'ha pogut detectar la llengua diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index 55d440186..6f66eeda1 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -288,6 +288,7 @@ I dag Oversæt Enhedsindstillinger + Kunne ikke finde sprog Fra Til Ulæst diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 2472f5a96..3622ce322 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -10,12 +10,14 @@ Avatar Ausente Opciones avanzadas de llamada + La llamada ha estado activa por una hora. Llamar sin avisar Los permisos para la cámara fueron otorgados. Por favor seleccione la cámara nuevamente. Elegir avatar desde la nube Borrar el mensaje de estado Borrar el mensaje de estado después de Cerrar + Bloquear grabación para grabación continua del mensaje de voz Conversaciones Zona de peligro Borrar avatar @@ -63,6 +65,7 @@ Permitir invitados Pin: %1$s Desbloquear %1$s + Para habilitar los parlantes bluetooth, por favor, otorgue el permiso \"Dispositivos cercanos\". Opciones avanzadas de llamada Contestar como videollamada Contestar como llamada de audio solamente @@ -86,6 +89,7 @@ %s llamada %s videollamada %s llamada de voz + Para habilitar la comunicación por vídeo, por favor, otorgue el permiso \"Cámara\". Para permitir la comunicación de vídeo, concede el permiso de \"Cámara\" en la configuración del sistema. Cancelar Fallo al recuperar capacidades. Abortando. @@ -207,6 +211,7 @@ Cancelar respuesta Mensajes leídos Mensaje enviado + Para habilitar la comunicación por voz, por favor, otorgue el permiso \"Micrófono\". Para permitir la comunicación de voz, concede el permiso de \"Micrófono\" en la configuración del sistema. Perdiste una llamada de %s Moderador @@ -240,7 +245,11 @@ Participantes Añadir participantes Contraseña + Establecer permisos + Algunos permisos fueron denegados. + Por favor, otorgue los permisos Abrir configuración + Por favor, otorgue los permisos en Ajustes > Permisos Cuenta no encontrada Chat a través de %s Silenciar micrófono diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml index d1e5d5e6d..de7f21ead 100644 --- a/app/src/main/res/values-fa/strings.xml +++ b/app/src/main/res/values-fa/strings.xml @@ -5,30 +5,50 @@ بلوتوث خروجی صدا شماره تلفن + Speaker + Wired headset آواتار دور + Advanced call options + The call has been running for one hour. + Call without notification + Camera permission granted. Please choose camera again. + Choose avatar from cloud پیام وضعیت را پاک کن بعد از آن پیام وضعیت را پاک کن بسته + Lock recording for continuously recording of the voice message گفتگو + Danger Zone آواتار را پاک کن مزاحم نشوید پاک نکن ویرایش + Backspace اخیر + Search emoji + Encrypted + There was a problem loading your chats + Failed to save %1$s پوشه بارگذاری … + %1$s (%2$d) ۴ ساعت نامرئی بار کردن نتیحه‌های بیش‌تر نماد قفل + Lower hand + Mentioned تازه‌ترین‌ها اول قدیمی‌ترین‌ها اول الف تا ی ی تا الف بزرگترین اول کوچک‌ترین اول + Tap to open poll جستجو نتیجه‌ای نداشت + Start typing to search … + Search … پیام ها حساب انتخاب‌شده اکنون وارد شده و در دسترس است . درباره @@ -43,10 +63,33 @@ افزودن‌ به مورد علاقه‌ها خوب ، همه انجام شد! اجازه میهمانان + Pin: %1$s باز کردن %1$s + To enable bluetooth speakers please grant \"Nearby devices\" permission. + Advanced call options + Answer as video call + Answer as voice call only + Change audio output + Toggle camera + Hang up + Toggle microphone + Open picture-in-picture mode + Switch to self video + INCOMING نام مکالمه نامی که وارد کردید با نام موجود یکسان است + Call notifications + %1$s raised the hand + Reconnecting … + RINGING + %1$s in call + %1$s with phone + %1$s with video در ۴۵ ثانیه پاسخی وجود نداشت ، برای آزمایش دوباره ضربه بزنید + %s call + %s video call + %s voice call + To enable video communication please grant \"Camera\" permission. برای فعال کردن ارتباطات تصویری ، لطفاً اجازه استفاده از \"دوربین\" را در تنظیمات سیستم قرار دهید. لغو دریافت قابلیت‌ها موفقیت‌آمیز نبود، درحال لغو @@ -61,12 +104,16 @@ آیا واقعا می‌خواهید تمام پیام‌ها را در این مکالمه حذف کنید؟ تغییر گواهی مشتری گواهی مشتری تنظیم کنید + Close app + and پنهان کن متاسفیم؛ خطایی پیش آمد تنظیم پرش گواهی تأیید اعتبار را انتخاب کنید + Connecting … انجام شد + Conversation description پیوند مکالمه اطلاعات مکالمه تماس تصویری @@ -75,6 +122,7 @@ عضو یک گفتگو شوید یا یک گفتگو جدید شروع کنید به رفقا و هم‌قطاران‌تان سلام کنید! کپی کردن + Create poll امروز دیروز حذف @@ -82,19 +130,34 @@ مکالمه را حذف کنید اگر این مکالمه را حذف کنید ، برای سایر شرکت کنندگان نیز حذف خواهد شد. حذف + Message deleted successfully, but it might have been leaked to other services تنزل مقام از مدیر ضبط پیام صوتی فرستادن پیام گذرواژه نادرست + Maintenance mode + Server is currently in maintenance mode. + App is outdated + The app is too old and no longer supported by this server. Please update. به‌روز رسانی + Do you want to reauthorize or delete this account? امکان دریافت نام وجود ندارد. درحال لغو "امکان ذخیره نام وجود ندارد، درحال لغو " رایانامه + 8 ساعت + 4 weeks خاموش + 1 روز ۱ ساعت + 1 week + Expire chat messages + Chat messages can be expired after a certain time. Note: Files shared in chat will not be deleted for the owner, but will no longer be shared in the conversation. " دریافت تنظیمات سیگنال نا‌موفق بود" + Target server does not support joining public conversations via mobile phones. You may attempt to join the conversation via web browser. با عرض پوزش، مشکلی پیش آمده بازگشت + Permission for file access is required + Filter Conversations کاربر پس از یک پیوند عمومی شما: %1$s ارسال کردن @@ -104,40 +167,74 @@ گروه گروه ها مهمان + Guest access + Cannot enable/disable guest access. + Allow guests to share a public link to join this conversation. اجازه میهمانان یک گذرواژه وارد کنید + Guest access password + Error during setting/disabling the password. + Set a password to restrict who can use the public link. محافظت از رمز عبور رمز عبور ضعیف + Resend invitations + Invitations were not send due to an error. + Invitations were sent out again. + Share conversation link + Enter a message … گفتگوی مهم + Notifications in this conversation will override Do Not Disturb settings با یک پیوند ملحق شوید از طریق وب ملحق شوید قبل از ترک ، باید یک مدیر جدید را تعیین کنید %1$s. نمی توان مکالمه را ترک کرد تغییرات %1$s | آخرین تغییرات: %2$s ترک صحبت + Leaving call … مجوز عمومی عمومی گنو ، نسخه 3 مجوز %sحد کاراکترها زده شده است + List open conversations لابی + This meeting is scheduled for %1$s + The meeting will start soon شما در حال حاضر در لابی منتظر هستید. + Your current location + location permission is required + Position unknown + Locked برای باز کردن قفل ضربه بزنید تنظیم نشده علامت به عنوان خوانده‌شده علامت به عنوان خوانده‌نشده + Failed to send message: لغو پاسخ + Message read پیام ارسال شد + To enable voice communication please grant \"Microphone\" permission. برای فعال کردن ارتباط صوتی ، لطفاً در \"تنظیمات سیستم\" اجازه استفاه از \"میکروفون\" را قرار دهید. + You missed a call from %s مدیر هرگز ملحق نشوید مکالمه جدید + Unread mentions پیام‌های خوانده نشده گذرواژه جدید + %1$s not available (not installed or restricted by admin) مهمان نه + No open conversations + No open conversations that you can join.\nEither there are no open conversations or you already joined all of them. پروکسی نیست + You are not allowed to activate audio! + You are not allowed to activate video! کانال اعلان %1$s روی %2$s + Calls + Notify about incoming calls پیام ها + Notify about incoming messages آپلودها + Notify about upload progress تنظیمات اعلان همیشه اعلان شود وقتی ذکر شد اطلاع دهید @@ -148,7 +245,15 @@ شركت كنندگان افزودن عضو گذرواژه + Set permissions + Some permissions were denied. + Please allow permissions تنظیمات را باز کنید + Please grant permissions at Settings > Permissions + Account not found + Chat via %s + Mute microphone + Enable microphone پیام ها حریم خصوصی ادامه @@ -159,10 +264,14 @@ دریافت اعلانات غیرفعال است برای صحبت کردن فشار دهید با غیر فعال کردن میکروفن، برای استفاده از Push-to-talk کلیک & نگه‌داشتن را انجام دهید + Remote audio off + Remove circle and members حذف کردن از مورد علاقه‌ها + Remove group and members شرکت کننده را حذف کنید تغییر نام مکالمه پاسخ + Reply privately ۳۰ ثانیه ۵ دقیقه ۱ دقیقه @@ -173,6 +282,7 @@ ۳۰۰ جستجو یک حساب کاربری انتخاب کنید + Select participants ارسال یک GIF %1$s. شما یک GIF ارسال کردید. ارسال یک فایل ویدئو %1$s. @@ -183,6 +293,12 @@ شما صوتی ارسال کردید. ارسال یک تصویر %1$s. شما یک تصویر ارسال کردید + %1$s sent a location. + You sent a location. + %1$s sent a poll. + You sent a poll. + %1$s sent a voice message. + You sent a voice message. آزمایش اتصال به سرور لطفا پایگاه داده %1$s خود را ارتقا دهید " وارد کردن حساب انتخاب‌شده موفقیت آمیز نبود" @@ -201,6 +317,7 @@ به جای اضافه کردن حساب جدید، حساب از قبل موجود شما بروز شد پیشرفته ظاهر + Calls دستورالعمل صفحه کلید را برای غیرفعال کردن یادگیری شخصی (بدون ضمانت) صفحه کلید ناشناس بدون صدا @@ -208,11 +325,21 @@ صدا آگاهی‌ها پیام ها + Match contacts based on phone number to integrate Talk shortcut into system contacts app + You can set your phone number so other users will be able to find you + Invalid phone number + Phone number set successfully شماره تلفن + Phone number integration حریم خصوصی میزبان پروکسی + Proxy password پورت پروکسی نوع پروکسی + Proxy username + Share my read-status and show the read-status of others + Read status + Reauthorize account حذف حذف حساب کاربری لطفاً قصد خود را برای حذف حساب جاری تأیید کنید. @@ -221,39 +348,96 @@ قفل صفحه از گرفتن عکسهای صفحه در لیست اخیر و داخل برنامه جلوگیری می کند امنیت صفحه نمایش + The server version is very old and will not be supported in the next release! + The server version is too old and not supported by this version of the Android app + Unsupported server تنظیم شده توسط ذخیره نیرو تیره از پیش‌فرض سیستم استفاده کنید تم روشن تم + Share my typing-status and show the typing-status of others + Typing status is only available when using a high performance backend (HPB) + Typing status + Proxy requires credentials هشدار فقط حساب کاربری فعلی قابل گرفتن مجوز مجدد است + Share contact + Permission to read contacts is required + Share current location + Share location دعوت %1$s به مکالمه %1$s/index.php/call/%2$s ملحق شوید رمز عبور: %1$s اشتراک این مکان حساب کاربری را انتخاب کنید + Shared items کارت deck + Images, files, voice messages … + No shared items محل + Shared location مرتب‌سازی بر اساس زمان شروع تعویض حساب + Choose files + Send these files to %1$s? + Send this file to %1$s? + Sorry, upload failed + Failed to upload %1$s + Failure + Share from %1$s + Upload from device در حال آپلود + %1$s to %2$s - %3$s\%% عکس گرفتن + Take video کاربر + Video recording from %1$s + Talk recording from %1$s (%2$s) + Hold to record, release to send. + Permission for audio recording is required + « Slide to cancel وبینار پیوند مکالمه معتبر نیست کلمه عبور اشتباه بله + No phone number integration due to missing permissions ۱ ساعت آنلاین وضعیت آنلاین مکالمه جدید + Open in Files app + Play/pause voice message + Add option + Edit vote + End poll + Do you really want to end this poll? This cannot be undone. + You cannot vote with more options for this poll. + Multiple answers + Delete option %1$s + Option %1$s گزینه‌ها + Private poll + Question + Your question نتایج تنظیمات + Vote + Vote submitted + Raise hand همه + Sharing files from storage is not possible without permissions + The call is being recorded + Cancel recording start + The recording failed. Please contact your administrator. + Start recording + Do you really want to stop the recording? + Stop Call recording + Stop recording + Stopping recording … + It\'s not possible to join other rooms while being in a call ذخیره فقط با سرورهای قابل اعتماد همگام سازی شود فدرال @@ -263,8 +447,16 @@ خصوصی با سرورهای قابل اعتماد و دفترچه آدرس عمومی و همگانی همگام سازی شود منتشر شده + Scope toggle + Change privacy level of %1$s + Scroll to bottom یک ثانیه پیش انتخاب شد + Send to + You are not allowed to share content to this chat + Send to … + Send without notification + Set avatar from camera تنظیم وضعیت تنظیم پیام وضعیت هم‌رسانی @@ -272,21 +464,43 @@ فایل رسانه‌ها اعلان‌ها + Poll + Call recording صدا مورد‌ ‌علاقه‌ + You are not allowed to start a call پیغام وضعیت + Switch to breakout room + Switch to main room عکس گرفتن + Error taking picture + Taking a photo is not possible without permissions + Re-take photo ارسال دوربین را عوض کنید + Crop photo + Reduce image size تغییر مشعل ۳۰ دقیقه این هفته + This is a test message پیوست ها امروز ترجمه + Translation + Copy translated text + Detect language تنظیمات افزاره + Could not detect language + Translation failed از به + and 1 other is typing … + are typing … + is typing … + and %1$s others are typing … + Unread + Upload new avatar from device نشانی نام کامل رایانامه @@ -294,7 +508,12 @@ توییتر وب‌ سایت وضعیت + Failed to retrieve personal user information. اطلاعات شخصی تنطیم نشده نام، تصویر و اطلاعات تماس را در صفحه نمایه خود اضافه کنید. وضعیت شما چیست؟ - + + %d vote + %d votes + + diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 6a92d2d71..63ded0bab 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -249,7 +249,7 @@ Vie privée Continuer Informations personnelles - Promouvoir en modérateur + Promouvoir comme modérateur Nouvelle conversation publique Les conversations publiques vous permettent d\'inviter des personnes extérieures grâce à un lien spécialement créé. Notifications push désactivées @@ -332,7 +332,7 @@ Statut de lecture Ré-autoriser le compte Effacer - Supprimer le compte + Retirer le compte Veuillez confirmer votre volonté de supprimer le compte actuel. Verrouiller %1$s avec le verrouillage d’écran Android ou une méthode biométrique supportée Délai d\'inactivité avant verrouillage de l\'écran diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index 819e4678e..9b3109527 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -151,7 +151,7 @@ 1 hora 1 semana Caducidade das mensaxes das parolas - As mensaxes das parolas poden caducar após dun tempo determinado. Nota: os ficheiros compartidos na parola non se eliminarán para o propietario, mais xa non se compartirán na conversa. + As mensaxes das parolas poden caducar após dun tempo determinado. Nota: Os ficheiros compartidos na parola non se eliminarán para o propietario, mais xa non se compartirán na conversa. Produciuse un fallo ao recuperar os axustes da sinalización O servidor de destino non admite unirse a conversas públicas mediante teléfonos móbiles. Pode tentar unirse á chamada empregando o navegador web. Desculpe, algo foi mal! diff --git a/app/src/main/res/values-ja-rJP/strings.xml b/app/src/main/res/values-ja-rJP/strings.xml index 49ae3bd87..1297beec2 100644 --- a/app/src/main/res/values-ja-rJP/strings.xml +++ b/app/src/main/res/values-ja-rJP/strings.xml @@ -9,6 +9,7 @@ 有線ヘッドセット アバター 離席中 + 通話が1 時間経過 通知なしで通話 クラウドからアバターを選択 ステータスメッセージを消去 @@ -137,6 +138,7 @@ グループ グループ ゲスト + ゲスト参加 ゲストを許可 パスワードを入力 パスワードを設定して、パブリックリンクを使用できるユーザーを制限します。 @@ -359,6 +361,9 @@ 挙手 (r) すべて ストレージからのファイル共有は権限がなければ不可能です + 録画開始をキャンセル + 録画を開始 + 録画を停止 保存 信頼できるサーバーのみと同期 連携 diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index f94fb52e9..4a2f79fc6 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -311,6 +311,7 @@ Denne uken Vedlegg I dag + Oversette Enhetsinnstillinger Fra Til diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index ec75637ac..bbbcbc1a7 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -10,6 +10,7 @@ Аватар Отошёл Дополнительные настройки звонка + Звонок длится уже час Звонок без уведомления Разрешение на камеру получено. Пожалуйста, выберите камеру снова. Выберите аватар из облака diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index 42b0b4f3e..5d36c90f8 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -10,12 +10,14 @@ Аватар Одсутан Напредне опције позива + Позив траје један сат. Позив без обавештења Дозвољен је приступ камери. Молимо вас да поново изаберете камеру Изаберите аватар из облака Обриши статусну поруку Обриши статусну поруку након Затвори + Закључајте снимање да би се гласовна порука непрестано снимала. Разговори Зона опасности Обриши аватар @@ -63,6 +65,7 @@ Дозволи госте Прикачено: %1$s Откључај %1$s + Ако желите да укључите bluetooth звучнике, молимо вас да дате дозволу „Оближњи уређаји” Напредне опције позива Одговори као видео позив Одговори као гласовни позив @@ -86,6 +89,7 @@ %s позив %s видео позив %s гласовни позив + Ако желите да укључите видео комуникацију, молимо вас да дате дозволу „Камера” Да бисте омогућили видео комуникацију, дозволите приступ камери у системским поставкама. Откажи Грешка приликом дохватања могућности, прекидам @@ -207,6 +211,7 @@ Откажи одговор Порука је прочитана Порука послата + Ако желите да укључите аудио комуникацију, молимо вас да дате дозволу „Микрофон” Да бисте омогућили аудио комуникацију, дозволите приступ микрофону у системским поставкама. Имате пропуштен позив од %s Модератор @@ -240,7 +245,11 @@ Учесници Додај учеснике Лозинка + Постави дозволе + Неке дозволе нису одобрене. + Молимо вас да дате дозволе Отвори поставке + Молимо вас да одобрите доволе у Подешавања > Дозволе Налог није нађен Чет преко %s Утули микрофон diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 3575d6032..6a9582d6b 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -280,19 +280,19 @@ %1$s надсилає голосове повідомлення. Ви надіслали голосове повідомлення. Перевірка з\'єднання з сервером - Будь ласка, оновіть Вашу %1$s базу даних + Будь ласка, оновіть вашу %1$s базу даних Не вдалося імпортувати обраний акаунт. Посилання на ваш веб-інтерфейс %1$s, коли ви відкриєте його у веб-переглядачі. Імпортувати обліковий запис із застосунку %1$s Імпорт акаунту Імпортувати облікові записти із застосунку %1$s Імпорт акаунтів - Будь ласка, вимкніть для %1$s режим обслуговування - Будь ласка, закінчіть Ваше %1$s встановлення + Будь ласка, вимкніть режим обслуговування для %1$s + Будь ласка, завершіть встановлення %1$s Перевірка з\'єднання На сервері не встановлено застосунок \"Talk\", який може підтримуватися Адреса сервера https://… - Робота додатка %1$s можлива тільки із серверами %2$s версії 13 або старше + Застосунок %1$s сумісний з %2$s версії 13 або вище Налаштування Замість створення нового облікового запису було виконано оновлення існуючого Додатково @@ -389,7 +389,7 @@ Ви справді хочете закінчити це опитування? Це не можна скасувати. Ви не можете голосувати більше ніж за один варіант у цьому опитуванні. Кілька відповідей - Видалити варіант %1$s + Вилучити варіант %1$s Варіант %1$s Параметри Приватне опитування diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 6b9176b2e..9d127d19f 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -223,8 +223,14 @@ Giơ tay Tất cả Lưu + Chỉ đồng bộ đối với máy chủ tin cậy Federated + Chỉ hiển thị với mọi người trong trường hợp này và khách + Cục bộ(ngoại tuyến) + Chỉ hiển thị với những người phù hợp thông qua tích hợp số điện thoại thông qua Talk trên thiết bị di động Riêng tư + Đồng bộ với máy chủ tin cậy và sổ danh bạ toàn cầu và công khai + Đã đăng Cuộn xuống dưới cùng vài giây trước Selected @@ -248,6 +254,7 @@ Hôm nay Dịch Cài đặt thiết bị + Không thể phát hiện ngôn ngữ Từ Tới Địa chỉ diff --git a/build.gradle b/build.gradle index 66e4743aa..474fa06a9 100644 --- a/build.gradle +++ b/build.gradle @@ -37,9 +37,9 @@ buildscript { classpath 'com.android.tools.build:gradle:8.1.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}" classpath "org.jetbrains.kotlin:kotlin-serialization:${kotlinVersion}" - classpath 'com.github.spotbugs.snom:spotbugs-gradle-plugin:5.1.1' + classpath 'com.github.spotbugs.snom:spotbugs-gradle-plugin:5.1.3' classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.23.1" - classpath "org.jlleitschuh.gradle:ktlint-gradle:11.5.0" + classpath "org.jlleitschuh.gradle:ktlint-gradle:11.5.1" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files