Reformatting

Signed-off-by: Mario Danic <mario@lovelyhq.com>
This commit is contained in:
Mario Danic 2019-10-17 13:12:29 +02:00
parent 8441fd2475
commit fd44934b98
234 changed files with 18720 additions and 17790 deletions

View File

@ -47,102 +47,111 @@ import javax.inject.Inject
@AutoInjector(NextcloudTalkApplication::class)
open class BaseActivity : AppCompatActivity() {
@Inject
lateinit var eventBus: EventBus
@Inject
lateinit var eventBus: EventBus
@Inject
lateinit var appPreferences: AppPreferences
@Inject
lateinit var appPreferences: AppPreferences
@Inject
lateinit var context: Context
@Inject
lateinit var context: Context
override fun onCreate(savedInstanceState: Bundle?) {
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
super.onCreate(savedInstanceState)
override fun onCreate(savedInstanceState: Bundle?) {
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
super.onCreate(savedInstanceState)
}
public override fun onResume() {
super.onResume()
if (appPreferences.isScreenSecured) {
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
} else {
window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
}
public override fun onResume() {
super.onResume()
if (appPreferences.isScreenSecured) {
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
} else {
window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
if (appPreferences.isScreenLocked) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
SecurityUtils.createKey(appPreferences.screenLockTimeout)
}
}
}
fun showCertificateDialog(
cert: X509Certificate,
magicTrustManager: MagicTrustManager,
sslErrorHandler: SslErrorHandler?
) {
val formatter = DateFormat.getDateInstance(DateFormat.LONG)
val validFrom = formatter.format(cert.notBefore)
val validUntil = formatter.format(cert.notAfter)
val issuedBy = cert.issuerDN.toString()
val issuedFor: String
try {
if (cert.subjectAlternativeNames != null) {
val stringBuilder = StringBuilder()
for (o in cert.subjectAlternativeNames) {
val list = o as List<*>
val type = list[0] as Int
if (type == 2) {
val name = list[1] as String
stringBuilder.append("[")
.append(type)
.append("]")
.append(name)
.append(" ")
}
}
issuedFor = stringBuilder.toString()
} else {
issuedFor = cert.subjectDN.name
}
if (appPreferences.isScreenLocked) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
SecurityUtils.createKey(appPreferences.screenLockTimeout)
}
}
@SuppressLint("StringFormatMatches") val dialogText = String.format(
resources
.getString(R.string.nc_certificate_dialog_text),
issuedBy, issuedFor, validFrom, validUntil
)
LovelyStandardDialog(this)
.setTopColorRes(R.color.nc_darkRed)
.setNegativeButtonColorRes(R.color.nc_darkRed)
.setPositiveButtonColorRes(R.color.colorPrimaryDark)
.setIcon(R.drawable.ic_security_white_24dp)
.setTitle(R.string.nc_certificate_dialog_title)
.setMessage(dialogText)
.setPositiveButton(R.string.nc_yes) { v ->
magicTrustManager.addCertInTrustStore(cert)
sslErrorHandler?.proceed()
}
.setNegativeButton(R.string.nc_no) { view1 ->
sslErrorHandler?.cancel()
}
.show()
} catch (e: CertificateParsingException) {
Log.d(TAG, "Failed to parse the certificate")
}
fun showCertificateDialog(cert: X509Certificate, magicTrustManager: MagicTrustManager,
sslErrorHandler: SslErrorHandler?) {
val formatter = DateFormat.getDateInstance(DateFormat.LONG)
val validFrom = formatter.format(cert.notBefore)
val validUntil = formatter.format(cert.notAfter)
}
val issuedBy = cert.issuerDN.toString()
val issuedFor: String
@Subscribe(threadMode = ThreadMode.MAIN)
fun onMessageEvent(event: CertificateEvent) {
showCertificateDialog(event.x509Certificate, event.magicTrustManager, event.sslErrorHandler)
}
try {
if (cert.subjectAlternativeNames != null) {
val stringBuilder = StringBuilder()
for (o in cert.subjectAlternativeNames) {
val list = o as List<*>
val type = list[0] as Int
if (type == 2) {
val name = list[1] as String
stringBuilder.append("[").append(type).append("]").append(name).append(" ")
}
}
issuedFor = stringBuilder.toString()
} else {
issuedFor = cert.subjectDN.name
}
public override fun onStart() {
super.onStart()
eventBus.register(this)
}
@SuppressLint("StringFormatMatches") val dialogText = String.format(resources
.getString(R.string.nc_certificate_dialog_text),
issuedBy, issuedFor, validFrom, validUntil)
public override fun onStop() {
super.onStop()
eventBus.unregister(this)
}
LovelyStandardDialog(this)
.setTopColorRes(R.color.nc_darkRed)
.setNegativeButtonColorRes(R.color.nc_darkRed)
.setPositiveButtonColorRes(R.color.colorPrimaryDark)
.setIcon(R.drawable.ic_security_white_24dp)
.setTitle(R.string.nc_certificate_dialog_title)
.setMessage(dialogText)
.setPositiveButton(R.string.nc_yes) { v ->
magicTrustManager.addCertInTrustStore(cert)
sslErrorHandler?.proceed()
}
.setNegativeButton(R.string.nc_no) { view1 ->
sslErrorHandler?.cancel()
}
.show()
} catch (e: CertificateParsingException) {
Log.d(TAG, "Failed to parse the certificate")
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
fun onMessageEvent(event: CertificateEvent) {
showCertificateDialog(event.x509Certificate, event.magicTrustManager, event.sslErrorHandler)
}
public override fun onStart() {
super.onStart()
eventBus.register(this)
}
public override fun onStop() {
super.onStop()
eventBus.unregister(this)
}
companion object {
private val TAG = "BaseActivity"
}
companion object {
private val TAG = "BaseActivity"
}
}

View File

@ -43,54 +43,60 @@ import com.nextcloud.talk.utils.bundle.BundleKeys
@AutoInjector(NextcloudTalkApplication::class)
class MagicCallActivity : BaseActivity() {
@BindView(R.id.controller_container)
lateinit var container: ViewGroup
@BindView(R.id.controller_container)
lateinit var container: ViewGroup
private var router: Router? = null
private var router: Router? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
requestWindowFeature(Window.FEATURE_NO_TITLE)
window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN or
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON or
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
window.decorView.systemUiVisibility = systemUiVisibility
requestWindowFeature(Window.FEATURE_NO_TITLE)
window.addFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN or
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON or
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
)
window.decorView.systemUiVisibility = systemUiVisibility
setContentView(R.layout.activity_magic_call)
setContentView(R.layout.activity_magic_call)
ButterKnife.bind(this)
router = Conductor.attachRouter(this, container, savedInstanceState)
router!!.setPopsLastView(false)
ButterKnife.bind(this)
router = Conductor.attachRouter(this, container, savedInstanceState)
router!!.setPopsLastView(false)
if (!router!!.hasRootController()) {
if (intent.getBooleanExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL, false)) {
router!!.setRoot(RouterTransaction.with(CallNotificationController(intent.extras))
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler()))
} else {
router!!.setRoot(RouterTransaction.with(CallController(intent.extras))
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler()))
}
}
if (!router!!.hasRootController()) {
if (intent.getBooleanExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL, false)) {
router!!.setRoot(
RouterTransaction.with(CallNotificationController(intent.extras))
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler())
)
} else {
router!!.setRoot(
RouterTransaction.with(CallController(intent.extras))
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler())
)
}
}
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
eventBus.post(ConfigurationChangeEvent())
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
eventBus.post(ConfigurationChangeEvent())
}
companion object {
private val TAG = "MagicCallActivity"
companion object {
private val TAG = "MagicCallActivity"
private val systemUiVisibility: Int
get() {
var flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_FULLSCREEN
flags = flags or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
return flags
}
}
private val systemUiVisibility: Int
get() {
var flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_FULLSCREEN
flags = flags or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
return flags
}
}
}

View File

@ -39,7 +39,6 @@ import com.google.android.material.appbar.MaterialToolbar
import com.nextcloud.talk.R
import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.controllers.CallNotificationController
import com.nextcloud.talk.controllers.ConversationsListController
import com.nextcloud.talk.controllers.LockedController
import com.nextcloud.talk.controllers.ServerSelectionController
import com.nextcloud.talk.controllers.base.providers.ActionBarProvider
@ -56,117 +55,129 @@ import javax.inject.Inject
@AutoInjector(NextcloudTalkApplication::class)
class MainActivity : BaseActivity(), ActionBarProvider {
@BindView(R.id.toolbar)
lateinit var toolbar: MaterialToolbar
@BindView(R.id.controller_container)
lateinit var container: ViewGroup
@BindView(R.id.toolbar)
lateinit var toolbar: MaterialToolbar
@BindView(R.id.controller_container)
lateinit var container: ViewGroup
@Inject
lateinit var userUtils: UserUtils
@Inject
lateinit var dataStore: ReactiveEntityStore<Persistable>
@Inject
lateinit var sqlCipherDatabaseSource: SqlCipherDatabaseSource
@Inject
lateinit var userUtils: UserUtils
@Inject
lateinit var dataStore: ReactiveEntityStore<Persistable>
@Inject
lateinit var sqlCipherDatabaseSource: SqlCipherDatabaseSource
private var router: Router? = null
private var router: Router? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setContentView(R.layout.activity_main)
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
ButterKnife.bind(this)
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
ButterKnife.bind(this)
setSupportActionBar(toolbar)
setSupportActionBar(toolbar)
router = Conductor.attachRouter(this, container, savedInstanceState)
router = Conductor.attachRouter(this, container, savedInstanceState)
var hasDb = true
var hasDb = true
try {
sqlCipherDatabaseSource.writableDatabase
} catch (exception: Exception) {
hasDb = false
}
if (intent.hasExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL)) {
if (!router!!.hasRootController()) {
router!!.setRoot(RouterTransaction.with(ConversationsListView())
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler()))
}
onNewIntent(intent)
} else if (!router!!.hasRootController()) {
if (hasDb) {
if (userUtils.anyUserExists()) {
router!!.setRoot(RouterTransaction.with(ConversationsListView())
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler()))
} else {
router!!.setRoot(RouterTransaction.with(ServerSelectionController())
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler()))
}
} else {
router!!.setRoot(RouterTransaction.with(ServerSelectionController())
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler()))
}
}
try {
sqlCipherDatabaseSource.writableDatabase
} catch (exception: Exception) {
hasDb = false
}
override fun onStart() {
super.onStart()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkIfWeAreSecure()
if (intent.hasExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL)) {
if (!router!!.hasRootController()) {
router!!.setRoot(
RouterTransaction.with(ConversationsListView())
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler())
)
}
onNewIntent(intent)
} else if (!router!!.hasRootController()) {
if (hasDb) {
if (userUtils.anyUserExists()) {
router!!.setRoot(
RouterTransaction.with(ConversationsListView())
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler())
)
} else {
router!!.setRoot(
RouterTransaction.with(ServerSelectionController())
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler())
)
}
} else {
router!!.setRoot(
RouterTransaction.with(ServerSelectionController())
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler())
)
}
}
}
override fun onStart() {
super.onStart()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkIfWeAreSecure()
}
}
@RequiresApi(api = Build.VERSION_CODES.M)
fun checkIfWeAreSecure() {
val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
if (keyguardManager.isKeyguardSecure && appPreferences.isScreenLocked) {
if (!SecurityUtils.checkIfWeAreAuthenticated(appPreferences.screenLockTimeout)) {
if (router != null && router!!.getControllerWithTag(LockedController.TAG) == null) {
router!!.pushController(
RouterTransaction.with(LockedController())
.pushChangeHandler(VerticalChangeHandler())
.popChangeHandler(VerticalChangeHandler())
.tag(LockedController.TAG)
)
}
}
}
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
if (intent.hasExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL)) {
if (intent.getBooleanExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL, false)) {
router!!.pushController(
RouterTransaction.with(CallNotificationController(intent.extras))
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler())
)
} else {
ConductorRemapping.remapChatController(
router!!, intent.getLongExtra(BundleKeys.KEY_INTERNAL_USER_ID, -1),
intent.getStringExtra(BundleKeys.KEY_ROOM_TOKEN), intent.extras!!, false
)
}
}
}
override fun onBackPressed() {
if (router!!.getControllerWithTag(LockedController.TAG) != null) {
return
}
@RequiresApi(api = Build.VERSION_CODES.M)
fun checkIfWeAreSecure() {
val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
if (keyguardManager.isKeyguardSecure && appPreferences.isScreenLocked) {
if (!SecurityUtils.checkIfWeAreAuthenticated(appPreferences.screenLockTimeout)) {
if (router != null && router!!.getControllerWithTag(LockedController.TAG) == null) {
router!!.pushController(RouterTransaction.with(LockedController())
.pushChangeHandler(VerticalChangeHandler())
.popChangeHandler(VerticalChangeHandler())
.tag(LockedController.TAG))
}
}
}
if (!router!!.handleBack()) {
super.onBackPressed()
}
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
if (intent.hasExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL)) {
if (intent.getBooleanExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL, false)) {
router!!.pushController(RouterTransaction.with(CallNotificationController(intent.extras))
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler()))
} else {
ConductorRemapping.remapChatController(router!!, intent.getLongExtra(BundleKeys.KEY_INTERNAL_USER_ID, -1),
intent.getStringExtra(BundleKeys.KEY_ROOM_TOKEN), intent.extras!!, false)
}
}
}
override fun onBackPressed() {
if (router!!.getControllerWithTag(LockedController.TAG) != null) {
return
}
if (!router!!.handleBack()) {
super.onBackPressed()
}
}
companion object {
private val TAG = "MainActivity"
}
companion object {
private val TAG = "MainActivity"
}
}

View File

@ -48,126 +48,134 @@ import eu.davidea.viewholders.FlexibleViewHolder;
import java.util.List;
import java.util.regex.Pattern;
public class AdvancedUserItem extends AbstractFlexibleItem<AdvancedUserItem.UserItemViewHolder> implements
IFilterable<String> {
public class AdvancedUserItem extends AbstractFlexibleItem<AdvancedUserItem.UserItemViewHolder>
implements
IFilterable<String> {
private Participant participant;
private UserEntity userEntity;
@Nullable
private Account account;
private Participant participant;
private UserEntity userEntity;
@Nullable
private Account account;
public AdvancedUserItem(Participant participant, UserEntity userEntity, @Nullable Account account) {
this.participant = participant;
this.userEntity = userEntity;
this.account = account;
public AdvancedUserItem(Participant participant, UserEntity userEntity,
@Nullable Account account) {
this.participant = participant;
this.userEntity = userEntity;
this.account = account;
}
@Override
public boolean equals(Object o) {
if (o instanceof AdvancedUserItem) {
AdvancedUserItem inItem = (AdvancedUserItem) o;
return participant.equals(inItem.getModel());
}
return false;
}
@Override
public int hashCode() {
return participant.hashCode();
}
/**
* @return the model object
*/
public Participant getModel() {
return participant;
}
public UserEntity getEntity() {
return userEntity;
}
@Nullable
public Account getAccount() {
return account;
}
@Override
public int getLayoutRes() {
return R.layout.rv_item_conversation;
}
@Override
public UserItemViewHolder createViewHolder(View view, FlexibleAdapter adapter) {
return new UserItemViewHolder(view, adapter);
}
@Override
public void bindViewHolder(FlexibleAdapter adapter, UserItemViewHolder holder, int position,
List payloads) {
holder.avatarImageView.setController(null);
if (adapter.hasFilter()) {
FlexibleUtils.highlightText(holder.contactDisplayName, participant.getName(),
String.valueOf(adapter.getFilter(String.class)),
NextcloudTalkApplication.Companion.getSharedApplication()
.getResources().getColor(R.color.colorPrimary));
} else {
holder.contactDisplayName.setText(participant.getName());
}
@Override
public boolean equals(Object o) {
if (o instanceof AdvancedUserItem) {
AdvancedUserItem inItem = (AdvancedUserItem) o;
return participant.equals(inItem.getModel());
}
return false;
}
holder.serverUrl.setText(userEntity.getBaseUrl());
@Override
public int hashCode() {
return participant.hashCode();
if (userEntity != null && userEntity.getBaseUrl() != null && userEntity.getBaseUrl()
.startsWith("http://") || userEntity.getBaseUrl().startsWith("https://")) {
holder.avatarImageView.setVisibility(View.VISIBLE);
DraweeController draweeController = Fresco.newDraweeControllerBuilder()
.setOldController(holder.avatarImageView.getController())
.setAutoPlayAnimations(true)
.setImageRequest(DisplayUtils.getImageRequestForUrl(
ApiUtils.getUrlForAvatarWithName(userEntity.getBaseUrl(),
participant.getUserId(), R.dimen.avatar_size), null))
.build();
holder.avatarImageView.setController(draweeController);
} else {
holder.avatarImageView.setVisibility(View.GONE);
RelativeLayout.LayoutParams layoutParams =
(RelativeLayout.LayoutParams) holder.linearLayout.getLayoutParams();
layoutParams.setMarginStart(
(int) NextcloudTalkApplication.Companion.getSharedApplication().getApplicationContext()
.getResources().getDimension(R.dimen.activity_horizontal_margin));
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_START);
holder.linearLayout.setLayoutParams(layoutParams);
}
}
@Override
public boolean filter(String constraint) {
return participant.getName() != null &&
Pattern.compile(constraint, Pattern.CASE_INSENSITIVE | Pattern.LITERAL)
.matcher(participant.getName().trim())
.find();
}
static class UserItemViewHolder extends FlexibleViewHolder {
@BindView(R.id.name_text)
public EmojiTextView contactDisplayName;
@BindView(R.id.secondary_text)
public TextView serverUrl;
@BindView(R.id.avatar_image)
public SimpleDraweeView avatarImageView;
@BindView(R.id.linear_layout)
LinearLayout linearLayout;
@BindView(R.id.more_menu)
ImageButton moreMenuButton;
@BindView(R.id.password_protected_image_view)
ImageView passwordProtectedImageView;
/**
* @return the model object
* Default constructor.
*/
public Participant getModel() {
return participant;
}
public UserEntity getEntity() {
return userEntity;
}
@Nullable
public Account getAccount() {
return account;
}
@Override
public int getLayoutRes() {
return R.layout.rv_item_conversation;
}
@Override
public UserItemViewHolder createViewHolder(View view, FlexibleAdapter adapter) {
return new UserItemViewHolder(view, adapter);
}
@Override
public void bindViewHolder(FlexibleAdapter adapter, UserItemViewHolder holder, int position, List payloads) {
holder.avatarImageView.setController(null);
if (adapter.hasFilter()) {
FlexibleUtils.highlightText(holder.contactDisplayName, participant.getName(),
String.valueOf(adapter.getFilter(String.class)), NextcloudTalkApplication.Companion.getSharedApplication()
.getResources().getColor(R.color.colorPrimary));
} else {
holder.contactDisplayName.setText(participant.getName());
}
holder.serverUrl.setText(userEntity.getBaseUrl());
if (userEntity != null && userEntity.getBaseUrl() != null && userEntity.getBaseUrl().startsWith("http://") || userEntity.getBaseUrl().startsWith("https://")) {
holder.avatarImageView.setVisibility(View.VISIBLE);
DraweeController draweeController = Fresco.newDraweeControllerBuilder()
.setOldController(holder.avatarImageView.getController())
.setAutoPlayAnimations(true)
.setImageRequest(DisplayUtils.getImageRequestForUrl(ApiUtils.getUrlForAvatarWithName(userEntity.getBaseUrl(),
participant.getUserId(), R.dimen.avatar_size), null))
.build();
holder.avatarImageView.setController(draweeController);
} else {
holder.avatarImageView.setVisibility(View.GONE);
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) holder.linearLayout.getLayoutParams();
layoutParams.setMarginStart((int) NextcloudTalkApplication.Companion.getSharedApplication().getApplicationContext()
.getResources().getDimension(R.dimen.activity_horizontal_margin));
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_START);
holder.linearLayout.setLayoutParams(layoutParams);
}
}
@Override
public boolean filter(String constraint) {
return participant.getName() != null &&
Pattern.compile(constraint, Pattern.CASE_INSENSITIVE | Pattern.LITERAL).matcher(participant.getName().trim()).find();
}
static class UserItemViewHolder extends FlexibleViewHolder {
@BindView(R.id.name_text)
public EmojiTextView contactDisplayName;
@BindView(R.id.secondary_text)
public TextView serverUrl;
@BindView(R.id.avatar_image)
public SimpleDraweeView avatarImageView;
@BindView(R.id.linear_layout)
LinearLayout linearLayout;
@BindView(R.id.more_menu)
ImageButton moreMenuButton;
@BindView(R.id.password_protected_image_view)
ImageView passwordProtectedImageView;
/**
* Default constructor.
*/
UserItemViewHolder(View view, FlexibleAdapter adapter) {
super(view, adapter);
ButterKnife.bind(this, view);
moreMenuButton.setVisibility(View.GONE);
passwordProtectedImageView.setVisibility(View.GONE);
}
UserItemViewHolder(View view, FlexibleAdapter adapter) {
super(view, adapter);
ButterKnife.bind(this, view);
moreMenuButton.setVisibility(View.GONE);
passwordProtectedImageView.setVisibility(View.GONE);
}
}
}

View File

@ -39,86 +39,89 @@ import eu.davidea.viewholders.FlexibleViewHolder;
import java.util.List;
public class AppItem extends AbstractFlexibleItem<AppItem.AppItemViewHolder> {
private String title;
private String packageName;
private String name;
@Nullable
private Drawable drawable;
private String title;
private String packageName;
private String name;
@Nullable
private Drawable drawable;
public AppItem(String title, String packageName, String name, @Nullable Drawable drawable) {
this.title = title;
this.packageName = packageName;
this.name = name;
this.drawable = drawable;
public AppItem(String title, String packageName, String name, @Nullable Drawable drawable) {
this.title = title;
this.packageName = packageName;
this.name = name;
this.drawable = drawable;
}
@Override
public boolean equals(Object o) {
if (o instanceof AppItem) {
AppItem inItem = (AppItem) o;
return title.equals(inItem.getTitle())
&& packageName.equals(inItem.getPackageName())
&& name.equals(inItem
.getName());
}
@Override
public boolean equals(Object o) {
if (o instanceof AppItem) {
AppItem inItem = (AppItem) o;
return title.equals(inItem.getTitle()) && packageName.equals(inItem.getPackageName()) && name.equals(inItem
.getName());
}
return false;
}
return false;
public String getTitle() {
return title;
}
public String getPackageName() {
return packageName;
}
public String getName() {
return name;
}
@Override
public int getLayoutRes() {
return R.layout.rv_item_app;
}
@Override
public void bindViewHolder(FlexibleAdapter<IFlexible> adapter, AppItemViewHolder holder,
int position, List<Object> payloads) {
if (drawable != null) {
holder.iconImageView.setVisibility(View.VISIBLE);
holder.iconImageView.setImageDrawable(drawable);
} else {
holder.iconImageView.setVisibility(View.GONE);
}
public String getTitle() {
return title;
if (position == 0) {
Spannable spannableString = new SpannableString(title);
spannableString.setSpan(
new ForegroundColorSpan(NextcloudTalkApplication.Companion.getSharedApplication()
.getResources().getColor(R.color.grey_600)), 0,
spannableString.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
holder.appTitleTextView.setText(spannableString);
} else {
holder.appTitleTextView.setText(title);
}
}
public String getPackageName() {
return packageName;
@Override
public AppItem.AppItemViewHolder createViewHolder(View view, FlexibleAdapter adapter) {
return new AppItemViewHolder(view, adapter);
}
static class AppItemViewHolder extends FlexibleViewHolder {
@BindView(R.id.icon_image_view)
public ImageView iconImageView;
@BindView(R.id.app_title_text_view)
public TextView appTitleTextView;
/**
* Default constructor.
*/
AppItemViewHolder(View view, FlexibleAdapter adapter) {
super(view, adapter);
ButterKnife.bind(this, view);
}
public String getName() {
return name;
}
@Override
public int getLayoutRes() {
return R.layout.rv_item_app;
}
@Override
public void bindViewHolder(FlexibleAdapter<IFlexible> adapter, AppItemViewHolder holder, int position, List<Object> payloads) {
if (drawable != null) {
holder.iconImageView.setVisibility(View.VISIBLE);
holder.iconImageView.setImageDrawable(drawable);
} else {
holder.iconImageView.setVisibility(View.GONE);
}
if (position == 0) {
Spannable spannableString = new SpannableString(title);
spannableString.setSpan(new ForegroundColorSpan(NextcloudTalkApplication.Companion.getSharedApplication()
.getResources().getColor(R.color.grey_600)), 0,
spannableString.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
holder.appTitleTextView.setText(spannableString);
} else {
holder.appTitleTextView.setText(title);
}
}
@Override
public AppItem.AppItemViewHolder createViewHolder(View view, FlexibleAdapter adapter) {
return new AppItemViewHolder(view, adapter);
}
static class AppItemViewHolder extends FlexibleViewHolder {
@BindView(R.id.icon_image_view)
public ImageView iconImageView;
@BindView(R.id.app_title_text_view)
public TextView appTitleTextView;
/**
* Default constructor.
*/
AppItemViewHolder(View view, FlexibleAdapter adapter) {
super(view, adapter);
ButterKnife.bind(this, view);
}
}
}
}

View File

@ -48,138 +48,145 @@ import java.util.List;
import java.util.regex.Pattern;
import org.greenrobot.eventbus.EventBus;
public class CallItem extends AbstractFlexibleItem<CallItem.RoomItemViewHolder> implements IFilterable<String> {
public class CallItem extends AbstractFlexibleItem<CallItem.RoomItemViewHolder>
implements IFilterable<String> {
private Conversation conversation;
private UserEntity userEntity;
private Conversation conversation;
private UserEntity userEntity;
public CallItem(Conversation conversation, UserEntity userEntity) {
this.conversation = conversation;
this.userEntity = userEntity;
public CallItem(Conversation conversation, UserEntity userEntity) {
this.conversation = conversation;
this.userEntity = userEntity;
}
@Override
public boolean equals(Object o) {
if (o instanceof CallItem) {
CallItem inItem = (CallItem) o;
return conversation.equals(inItem.getModel());
}
return false;
}
@Override
public int hashCode() {
return conversation.hashCode();
}
/**
* @return the model object
*/
public Conversation getModel() {
return conversation;
}
/**
* Filter is applied to the model fields.
*/
@Override
public int getLayoutRes() {
return R.layout.rv_item_conversation;
}
@Override
public RoomItemViewHolder createViewHolder(View view, FlexibleAdapter adapter) {
return new RoomItemViewHolder(view, adapter);
}
@Override
public void bindViewHolder(final FlexibleAdapter adapter, RoomItemViewHolder holder, int position,
List payloads) {
if (adapter.hasFilter()) {
FlexibleUtils.highlightText(holder.roomDisplayName, conversation.getDisplayName(),
String.valueOf(adapter.getFilter(String.class)),
NextcloudTalkApplication.Companion.getSharedApplication()
.getResources().getColor(R.color.colorPrimary));
} else {
holder.roomDisplayName.setText(conversation.getDisplayName());
}
@Override
public boolean equals(Object o) {
if (o instanceof CallItem) {
CallItem inItem = (CallItem) o;
return conversation.equals(inItem.getModel());
}
return false;
if (conversation.getLastPing() == 0) {
holder.roomLastPing.setText(R.string.nc_never);
} else {
holder.roomLastPing.setText(
DateUtils.getRelativeTimeSpanString(conversation.getLastPing() * 1000L,
System.currentTimeMillis(), 0, DateUtils.FORMAT_ABBREV_RELATIVE));
}
@Override
public int hashCode() {
return conversation.hashCode();
if (conversation.hasPassword) {
holder.passwordProtectedImageView.setVisibility(View.VISIBLE);
} else {
holder.passwordProtectedImageView.setVisibility(View.GONE);
}
/**
* @return the model object
*/
Resources resources = NextcloudTalkApplication.Companion.getSharedApplication().getResources();
switch (conversation.getType()) {
case ROOM_TYPE_ONE_TO_ONE_CALL:
holder.avatarImageView.setVisibility(View.VISIBLE);
public Conversation getModel() {
return conversation;
}
holder.moreMenuButton.setContentDescription(String.format(resources.getString(R.string
.nc_description_more_menu_one_to_one), conversation.getDisplayName()));
/**
* Filter is applied to the model fields.
*/
@Override
public int getLayoutRes() {
return R.layout.rv_item_conversation;
}
@Override
public RoomItemViewHolder createViewHolder(View view, FlexibleAdapter adapter) {
return new RoomItemViewHolder(view, adapter);
}
@Override
public void bindViewHolder(final FlexibleAdapter adapter, RoomItemViewHolder holder, int position, List payloads) {
if (adapter.hasFilter()) {
FlexibleUtils.highlightText(holder.roomDisplayName, conversation.getDisplayName(),
String.valueOf(adapter.getFilter(String.class)), NextcloudTalkApplication.Companion.getSharedApplication()
.getResources().getColor(R.color.colorPrimary));
if (!TextUtils.isEmpty(conversation.getName())) {
DraweeController draweeController = Fresco.newDraweeControllerBuilder()
.setOldController(holder.avatarImageView.getController())
.setAutoPlayAnimations(true)
.setImageRequest(DisplayUtils.getImageRequestForUrl(
ApiUtils.getUrlForAvatarWithName(userEntity.getBaseUrl(),
conversation.getName(),
R.dimen.avatar_size), null))
.build();
holder.avatarImageView.setController(draweeController);
} else {
holder.roomDisplayName.setText(conversation.getDisplayName());
holder.avatarImageView.setVisibility(View.GONE);
}
if (conversation.getLastPing() == 0) {
holder.roomLastPing.setText(R.string.nc_never);
} else {
holder.roomLastPing.setText(DateUtils.getRelativeTimeSpanString(conversation.getLastPing() * 1000L,
System.currentTimeMillis(), 0, DateUtils.FORMAT_ABBREV_RELATIVE));
}
if (conversation.hasPassword) {
holder.passwordProtectedImageView.setVisibility(View.VISIBLE);
} else {
holder.passwordProtectedImageView.setVisibility(View.GONE);
}
Resources resources = NextcloudTalkApplication.Companion.getSharedApplication().getResources();
switch (conversation.getType()) {
case ROOM_TYPE_ONE_TO_ONE_CALL:
holder.avatarImageView.setVisibility(View.VISIBLE);
holder.moreMenuButton.setContentDescription(String.format(resources.getString(R.string
.nc_description_more_menu_one_to_one), conversation.getDisplayName()));
if (!TextUtils.isEmpty(conversation.getName())) {
DraweeController draweeController = Fresco.newDraweeControllerBuilder()
.setOldController(holder.avatarImageView.getController())
.setAutoPlayAnimations(true)
.setImageRequest(DisplayUtils.getImageRequestForUrl(ApiUtils.getUrlForAvatarWithName(userEntity.getBaseUrl(),
conversation.getName(),
R.dimen.avatar_size), null))
.build();
holder.avatarImageView.setController(draweeController);
} else {
holder.avatarImageView.setVisibility(View.GONE);
}
break;
case ROOM_GROUP_CALL:
holder.moreMenuButton.setContentDescription(String.format(resources.getString(R.string
.nc_description_more_menu_group), conversation.getDisplayName()));
holder.avatarImageView.setActualImageResource(R.drawable.ic_people_group_white_24px);
holder.avatarImageView.setVisibility(View.VISIBLE);
break;
case ROOM_PUBLIC_CALL:
holder.moreMenuButton.setContentDescription(String.format(resources.getString(R.string
.nc_description_more_menu_public), conversation.getDisplayName()));
holder.avatarImageView.setActualImageResource(R.drawable.ic_link_white_24px);
holder.avatarImageView.setVisibility(View.VISIBLE);
break;
default:
holder.avatarImageView.setVisibility(View.GONE);
}
holder.moreMenuButton.setOnClickListener(view -> EventBus.getDefault().post(new MoreMenuClickEvent(conversation)));
break;
case ROOM_GROUP_CALL:
holder.moreMenuButton.setContentDescription(String.format(resources.getString(R.string
.nc_description_more_menu_group), conversation.getDisplayName()));
holder.avatarImageView.setActualImageResource(R.drawable.ic_people_group_white_24px);
holder.avatarImageView.setVisibility(View.VISIBLE);
break;
case ROOM_PUBLIC_CALL:
holder.moreMenuButton.setContentDescription(String.format(resources.getString(R.string
.nc_description_more_menu_public), conversation.getDisplayName()));
holder.avatarImageView.setActualImageResource(R.drawable.ic_link_white_24px);
holder.avatarImageView.setVisibility(View.VISIBLE);
break;
default:
holder.avatarImageView.setVisibility(View.GONE);
}
@Override
public boolean filter(String constraint) {
return conversation.getDisplayName() != null &&
Pattern.compile(constraint, Pattern.CASE_INSENSITIVE | Pattern.LITERAL).matcher(conversation.getDisplayName().trim()).find();
}
static class RoomItemViewHolder extends FlexibleViewHolder {
@BindView(R.id.name_text)
public EmojiTextView roomDisplayName;
@BindView(R.id.secondary_text)
public EmojiTextView roomLastPing;
@BindView(R.id.avatar_image)
public SimpleDraweeView avatarImageView;
@BindView(R.id.more_menu)
public ImageButton moreMenuButton;
@BindView(R.id.password_protected_image_view)
ImageView passwordProtectedImageView;
RoomItemViewHolder(View view, FlexibleAdapter adapter) {
super(view, adapter);
ButterKnife.bind(this, view);
}
holder.moreMenuButton.setOnClickListener(
view -> EventBus.getDefault().post(new MoreMenuClickEvent(conversation)));
}
@Override
public boolean filter(String constraint) {
return conversation.getDisplayName() != null &&
Pattern.compile(constraint, Pattern.CASE_INSENSITIVE | Pattern.LITERAL)
.matcher(conversation.getDisplayName().trim())
.find();
}
static class RoomItemViewHolder extends FlexibleViewHolder {
@BindView(R.id.name_text)
public EmojiTextView roomDisplayName;
@BindView(R.id.secondary_text)
public EmojiTextView roomLastPing;
@BindView(R.id.avatar_image)
public SimpleDraweeView avatarImageView;
@BindView(R.id.more_menu)
public ImageButton moreMenuButton;
@BindView(R.id.password_protected_image_view)
ImageView passwordProtectedImageView;
RoomItemViewHolder(View view, FlexibleAdapter adapter) {
super(view, adapter);
ButterKnife.bind(this, view);
}
}
}

View File

@ -35,11 +35,11 @@ import butterknife.ButterKnife;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.drawee.interfaces.DraweeController;
import com.facebook.drawee.view.SimpleDraweeView;
import com.nextcloud.talk.models.json.conversations.Conversation;
import com.nextcloud.talk.R;
import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.models.database.UserEntity;
import com.nextcloud.talk.models.json.chat.ChatMessage;
import com.nextcloud.talk.models.json.conversations.Conversation;
import com.nextcloud.talk.utils.ApiUtils;
import com.nextcloud.talk.utils.DisplayUtils;
import eu.davidea.flexibleadapter.FlexibleAdapter;
@ -51,215 +51,233 @@ import eu.davidea.viewholders.FlexibleViewHolder;
import java.util.List;
import java.util.regex.Pattern;
public class ConversationItem extends AbstractFlexibleItem<ConversationItem.ConversationItemViewHolder> implements
IFilterable<String> {
public class ConversationItem
extends AbstractFlexibleItem<ConversationItem.ConversationItemViewHolder> implements
IFilterable<String> {
private Conversation conversation;
private UserEntity userEntity;
private Context context;
private Conversation conversation;
private UserEntity userEntity;
private Context context;
public ConversationItem(Conversation conversation, UserEntity userEntity,
Context activityContext) {
this.conversation = conversation;
this.userEntity = userEntity;
this.context = activityContext;
}
public ConversationItem(Conversation conversation, UserEntity userEntity,
Context activityContext) {
this.conversation = conversation;
this.userEntity = userEntity;
this.context = activityContext;
@Override
public boolean equals(Object o) {
if (o instanceof ConversationItem) {
ConversationItem inItem = (ConversationItem) o;
return conversation.equals(inItem.getModel());
}
return false;
}
public Conversation getModel() {
return conversation;
}
@Override
public int hashCode() {
return conversation.hashCode();
}
@Override
public int getLayoutRes() {
return R.layout.rv_item_conversation_with_last_message;
}
@Override
public ConversationItemViewHolder createViewHolder(View view,
FlexibleAdapter<IFlexible> adapter) {
return new ConversationItemViewHolder(view, adapter);
}
@Override
public void bindViewHolder(FlexibleAdapter<IFlexible> adapter, ConversationItemViewHolder holder,
int position, List<Object> payloads) {
Context appContext =
NextcloudTalkApplication.Companion.getSharedApplication().getApplicationContext();
holder.dialogAvatar.setController(null);
if (adapter.hasFilter()) {
FlexibleUtils.highlightText(holder.dialogName, conversation.getDisplayName(),
String.valueOf(adapter.getFilter(String.class)),
NextcloudTalkApplication.Companion.getSharedApplication()
.getResources().getColor(R.color.colorPrimary));
} else {
holder.dialogName.setText(conversation.getDisplayName());
}
@Override
public boolean equals(Object o) {
if (o instanceof ConversationItem) {
ConversationItem inItem = (ConversationItem) o;
return conversation.equals(inItem.getModel());
}
return false;
if (conversation.getUnreadMessages() > 0) {
holder.dialogUnreadBubble.setVisibility(View.VISIBLE);
if (conversation.getUnreadMessages() < 100) {
holder.dialogUnreadBubble.setText(Long.toString(conversation.getUnreadMessages()));
} else {
holder.dialogUnreadBubble.setText("99+");
}
if (conversation.isUnreadMention()) {
holder.dialogUnreadBubble.setBackground(
context.getDrawable(R.drawable.bubble_circle_unread_mention));
} else {
holder.dialogUnreadBubble.setBackground(
context.getDrawable(R.drawable.bubble_circle_unread));
}
} else {
holder.dialogUnreadBubble.setVisibility(View.GONE);
}
public Conversation getModel() {
return conversation;
if (conversation.isHasPassword()) {
holder.passwordProtectedRoomImageView.setVisibility(View.VISIBLE);
} else {
holder.passwordProtectedRoomImageView.setVisibility(View.GONE);
}
@Override
public int hashCode() {
return conversation.hashCode();
if (conversation.isFavorite()) {
holder.pinnedConversationImageView.setVisibility(View.VISIBLE);
} else {
holder.pinnedConversationImageView.setVisibility(View.GONE);
}
@Override
public int getLayoutRes() {
return R.layout.rv_item_conversation_with_last_message;
}
if (conversation.getLastMessage() != null) {
holder.dialogDate.setVisibility(View.VISIBLE);
holder.dialogDate.setText(
DateUtils.getRelativeTimeSpanString(conversation.getLastActivity() * 1000L,
System.currentTimeMillis(), 0, DateUtils.FORMAT_ABBREV_RELATIVE));
@Override
public ConversationItemViewHolder createViewHolder(View view, FlexibleAdapter<IFlexible> adapter) {
return new ConversationItemViewHolder(view, adapter);
}
@Override
public void bindViewHolder(FlexibleAdapter<IFlexible> adapter, ConversationItemViewHolder holder, int position, List<Object> payloads) {
Context appContext =
NextcloudTalkApplication.Companion.getSharedApplication().getApplicationContext();
holder.dialogAvatar.setController(null);
if (adapter.hasFilter()) {
FlexibleUtils.highlightText(holder.dialogName, conversation.getDisplayName(),
String.valueOf(adapter.getFilter(String.class)), NextcloudTalkApplication.Companion.getSharedApplication()
.getResources().getColor(R.color.colorPrimary));
if (!TextUtils.isEmpty(conversation.getLastMessage().getSystemMessage())
|| Conversation.ConversationType.ROOM_SYSTEM.equals(conversation.getType())) {
holder.dialogLastMessage.setText(conversation.getLastMessage().getText());
} else {
String authorDisplayName = "";
conversation.getLastMessage().setActiveUser(userEntity);
String text;
if (conversation.getLastMessage()
.getMessageType()
.equals(ChatMessage.MessageType.REGULAR_TEXT_MESSAGE)) {
if (conversation.getLastMessage().getActorId().equals(userEntity.getUserId())) {
text = String.format(appContext.getString(R.string.nc_formatted_message_you),
conversation.getLastMessage().getLastMessageDisplayText());
} else {
authorDisplayName =
!TextUtils.isEmpty(conversation.getLastMessage().getActorDisplayName()) ?
conversation.getLastMessage().getActorDisplayName() :
"guests".equals(conversation.getLastMessage().getActorType())
? appContext.getString(R.string.nc_guest) : "";
text = String.format(appContext.getString(R.string.nc_formatted_message),
authorDisplayName,
conversation.getLastMessage().getLastMessageDisplayText());
}
} else {
holder.dialogName.setText(conversation.getDisplayName());
text = conversation.getLastMessage().getLastMessageDisplayText();
}
if (conversation.getUnreadMessages() > 0) {
holder.dialogUnreadBubble.setVisibility(View.VISIBLE);
if (conversation.getUnreadMessages() < 100) {
holder.dialogUnreadBubble.setText(Long.toString(conversation.getUnreadMessages()));
} else {
holder.dialogUnreadBubble.setText("99+");
}
if (conversation.isUnreadMention()) {
holder.dialogUnreadBubble.setBackground(context.getDrawable(R.drawable.bubble_circle_unread_mention));
} else {
holder.dialogUnreadBubble.setBackground(context.getDrawable(R.drawable.bubble_circle_unread));
}
} else {
holder.dialogUnreadBubble.setVisibility(View.GONE);
}
if (conversation.isHasPassword()) {
holder.passwordProtectedRoomImageView.setVisibility(View.VISIBLE);
} else {
holder.passwordProtectedRoomImageView.setVisibility(View.GONE);
}
if (conversation.isFavorite()) {
holder.pinnedConversationImageView.setVisibility(View.VISIBLE);
} else {
holder.pinnedConversationImageView.setVisibility(View.GONE);
}
if (conversation.getLastMessage() != null) {
holder.dialogDate.setVisibility(View.VISIBLE);
holder.dialogDate.setText(DateUtils.getRelativeTimeSpanString(conversation.getLastActivity() * 1000L,
System.currentTimeMillis(), 0, DateUtils.FORMAT_ABBREV_RELATIVE));
if (!TextUtils.isEmpty(conversation.getLastMessage().getSystemMessage()) || Conversation.ConversationType.ROOM_SYSTEM.equals(conversation.getType())) {
holder.dialogLastMessage.setText(conversation.getLastMessage().getText());
} else {
String authorDisplayName = "";
conversation.getLastMessage().setActiveUser(userEntity);
String text;
if (conversation.getLastMessage().getMessageType().equals(ChatMessage.MessageType.REGULAR_TEXT_MESSAGE)) {
if (conversation.getLastMessage().getActorId().equals(userEntity.getUserId())) {
text = String.format(appContext.getString(R.string.nc_formatted_message_you),
conversation.getLastMessage().getLastMessageDisplayText());
} else {
authorDisplayName = !TextUtils.isEmpty(conversation.getLastMessage().getActorDisplayName()) ?
conversation.getLastMessage().getActorDisplayName() :
"guests".equals(conversation.getLastMessage().getActorType()) ? appContext.getString(R.string.nc_guest) : "";
text = String.format(appContext.getString(R.string.nc_formatted_message),
authorDisplayName,
conversation.getLastMessage().getLastMessageDisplayText());
}
} else {
text = conversation.getLastMessage().getLastMessageDisplayText();
}
holder.dialogLastMessage.setText(text);
}
} else {
holder.dialogDate.setVisibility(View.GONE);
holder.dialogLastMessage.setText(R.string.nc_no_messages_yet);
}
holder.dialogAvatar.setVisibility(View.VISIBLE);
boolean shouldLoadAvatar = true;
String objectType;
if (!TextUtils.isEmpty(objectType = conversation.getObjectType())) {
switch (objectType) {
case "share:password":
shouldLoadAvatar = false;
holder.dialogAvatar.getHierarchy().setImage(new BitmapDrawable(DisplayUtils
.getRoundedBitmapFromVectorDrawableResource(context.getResources(),
R.drawable.ic_file_password_request)), 100, true);
break;
case "file":
shouldLoadAvatar = false;
holder.dialogAvatar.getHierarchy().setImage(new BitmapDrawable(DisplayUtils
.getRoundedBitmapFromVectorDrawableResource(context.getResources(),
R.drawable.ic_file_icon)), 100, true);
break;
default:
break;
}
}
if (Conversation.ConversationType.ROOM_SYSTEM.equals(conversation.getType())) {
Drawable[] layers = new Drawable[2];
layers[0] = context.getDrawable(R.drawable.ic_launcher_background);
layers[1] = context.getDrawable(R.drawable.ic_launcher_foreground);
LayerDrawable layerDrawable = new LayerDrawable(layers);
holder.dialogAvatar.getHierarchy().setPlaceholderImage(DisplayUtils.getRoundedDrawable(layerDrawable));
shouldLoadAvatar = false;
}
if (shouldLoadAvatar) {
switch (conversation.getType()) {
case ROOM_TYPE_ONE_TO_ONE_CALL:
if (!TextUtils.isEmpty(conversation.getName())) {
DraweeController draweeController = Fresco.newDraweeControllerBuilder()
.setOldController(holder.dialogAvatar.getController())
.setAutoPlayAnimations(true)
.setImageRequest(DisplayUtils.getImageRequestForUrl(ApiUtils.getUrlForAvatarWithName(userEntity.getBaseUrl(), conversation.getName(), R.dimen.avatar_size), null))
.build();
holder.dialogAvatar.setController(draweeController);
} else {
holder.dialogAvatar.setVisibility(View.GONE);
}
break;
case ROOM_GROUP_CALL:
holder.dialogAvatar.getHierarchy().setImage(new BitmapDrawable(DisplayUtils.getRoundedBitmapFromVectorDrawableResource(context.getResources(), R.drawable.ic_people_group_white_24px)), 100, true);
break;
case ROOM_PUBLIC_CALL:
holder.dialogAvatar.getHierarchy().setImage(new BitmapDrawable(DisplayUtils
.getRoundedBitmapFromVectorDrawableResource(context.getResources(),
R.drawable.ic_link_white_24px)), 100, true);
break;
default:
holder.dialogAvatar.setVisibility(View.GONE);
}
}
holder.dialogLastMessage.setText(text);
}
} else {
holder.dialogDate.setVisibility(View.GONE);
holder.dialogLastMessage.setText(R.string.nc_no_messages_yet);
}
@Override
public boolean filter(String constraint) {
return conversation.getDisplayName() != null &&
Pattern.compile(constraint, Pattern.CASE_INSENSITIVE | Pattern.LITERAL).matcher(conversation.getDisplayName().trim()).find();
holder.dialogAvatar.setVisibility(View.VISIBLE);
boolean shouldLoadAvatar = true;
String objectType;
if (!TextUtils.isEmpty(objectType = conversation.getObjectType())) {
switch (objectType) {
case "share:password":
shouldLoadAvatar = false;
holder.dialogAvatar.getHierarchy().setImage(new BitmapDrawable(DisplayUtils
.getRoundedBitmapFromVectorDrawableResource(context.getResources(),
R.drawable.ic_file_password_request)), 100, true);
break;
case "file":
shouldLoadAvatar = false;
holder.dialogAvatar.getHierarchy().setImage(new BitmapDrawable(DisplayUtils
.getRoundedBitmapFromVectorDrawableResource(context.getResources(),
R.drawable.ic_file_icon)), 100, true);
break;
default:
break;
}
}
static class ConversationItemViewHolder extends FlexibleViewHolder {
@BindView(R.id.dialogAvatar)
SimpleDraweeView dialogAvatar;
@BindView(R.id.dialogName)
EmojiTextView dialogName;
@BindView(R.id.dialogDate)
TextView dialogDate;
@BindView(R.id.dialogLastMessage)
EmojiTextView dialogLastMessage;
@BindView(R.id.dialogUnreadBubble)
TextView dialogUnreadBubble;
@BindView(R.id.passwordProtectedRoomImageView)
ImageView passwordProtectedRoomImageView;
@BindView(R.id.favoriteConversationImageView)
ImageView pinnedConversationImageView;
if (Conversation.ConversationType.ROOM_SYSTEM.equals(conversation.getType())) {
Drawable[] layers = new Drawable[2];
layers[0] = context.getDrawable(R.drawable.ic_launcher_background);
layers[1] = context.getDrawable(R.drawable.ic_launcher_foreground);
LayerDrawable layerDrawable = new LayerDrawable(layers);
ConversationItemViewHolder(View view, FlexibleAdapter adapter) {
super(view, adapter);
ButterKnife.bind(this, view);
}
holder.dialogAvatar.getHierarchy()
.setPlaceholderImage(DisplayUtils.getRoundedDrawable(layerDrawable));
shouldLoadAvatar = false;
}
if (shouldLoadAvatar) {
switch (conversation.getType()) {
case ROOM_TYPE_ONE_TO_ONE_CALL:
if (!TextUtils.isEmpty(conversation.getName())) {
DraweeController draweeController = Fresco.newDraweeControllerBuilder()
.setOldController(holder.dialogAvatar.getController())
.setAutoPlayAnimations(true)
.setImageRequest(DisplayUtils.getImageRequestForUrl(
ApiUtils.getUrlForAvatarWithName(userEntity.getBaseUrl(),
conversation.getName(), R.dimen.avatar_size), null))
.build();
holder.dialogAvatar.setController(draweeController);
} else {
holder.dialogAvatar.setVisibility(View.GONE);
}
break;
case ROOM_GROUP_CALL:
holder.dialogAvatar.getHierarchy()
.setImage(new BitmapDrawable(
DisplayUtils.getRoundedBitmapFromVectorDrawableResource(context.getResources(),
R.drawable.ic_people_group_white_24px)), 100, true);
break;
case ROOM_PUBLIC_CALL:
holder.dialogAvatar.getHierarchy().setImage(new BitmapDrawable(DisplayUtils
.getRoundedBitmapFromVectorDrawableResource(context.getResources(),
R.drawable.ic_link_white_24px)), 100, true);
break;
default:
holder.dialogAvatar.setVisibility(View.GONE);
}
}
}
@Override
public boolean filter(String constraint) {
return conversation.getDisplayName() != null &&
Pattern.compile(constraint, Pattern.CASE_INSENSITIVE | Pattern.LITERAL)
.matcher(conversation.getDisplayName().trim())
.find();
}
static class ConversationItemViewHolder extends FlexibleViewHolder {
@BindView(R.id.dialogAvatar)
SimpleDraweeView dialogAvatar;
@BindView(R.id.dialogName)
EmojiTextView dialogName;
@BindView(R.id.dialogDate)
TextView dialogDate;
@BindView(R.id.dialogLastMessage)
EmojiTextView dialogLastMessage;
@BindView(R.id.dialogUnreadBubble)
TextView dialogUnreadBubble;
@BindView(R.id.passwordProtectedRoomImageView)
ImageView passwordProtectedRoomImageView;
@BindView(R.id.favoriteConversationImageView)
ImageView pinnedConversationImageView;
ConversationItemViewHolder(View view, FlexibleAdapter adapter) {
super(view, adapter);
ButterKnife.bind(this, view);
}
}
}

View File

@ -32,63 +32,63 @@ import eu.davidea.flexibleadapter.items.IFlexible;
import eu.davidea.viewholders.FlexibleViewHolder;
import java.util.List;
public class GenericTextHeaderItem extends AbstractHeaderItem<GenericTextHeaderItem.HeaderViewHolder> {
private static final String TAG = "GenericTextHeaderItem";
public class GenericTextHeaderItem
extends AbstractHeaderItem<GenericTextHeaderItem.HeaderViewHolder> {
private static final String TAG = "GenericTextHeaderItem";
private String title;
private String title;
public GenericTextHeaderItem(String title) {
super();
setHidden(false);
setSelectable(false);
this.title = title;
public GenericTextHeaderItem(String title) {
super();
setHidden(false);
setSelectable(false);
this.title = title;
}
public String getModel() {
return title;
}
@Override
public boolean equals(Object o) {
if (o instanceof GenericTextHeaderItem) {
GenericTextHeaderItem inItem = (GenericTextHeaderItem) o;
return title.equals(inItem.getModel());
}
return false;
}
public String getModel() {
return title;
@Override
public int getLayoutRes() {
return R.layout.rv_item_title_header;
}
@Override
public void bindViewHolder(FlexibleAdapter<IFlexible> adapter, HeaderViewHolder holder,
int position, List<Object> payloads) {
if (payloads.size() > 0) {
Log.d(TAG, "We have payloads, so ignoring!");
} else {
holder.titleTextView.setText(title);
}
}
@Override
public boolean equals(Object o) {
if (o instanceof GenericTextHeaderItem) {
GenericTextHeaderItem inItem = (GenericTextHeaderItem) o;
return title.equals(inItem.getModel());
}
return false;
@Override
public HeaderViewHolder createViewHolder(View view, FlexibleAdapter adapter) {
return new HeaderViewHolder(view, adapter);
}
static class HeaderViewHolder extends FlexibleViewHolder {
@BindView(R.id.title_text_view)
public TextView titleTextView;
/**
* Default constructor.
*/
HeaderViewHolder(View view, FlexibleAdapter adapter) {
super(view, adapter, true);
ButterKnife.bind(this, view);
}
@Override
public int getLayoutRes() {
return R.layout.rv_item_title_header;
}
@Override
public void bindViewHolder(FlexibleAdapter<IFlexible> adapter, HeaderViewHolder holder, int position, List<Object> payloads) {
if (payloads.size() > 0) {
Log.d(TAG, "We have payloads, so ignoring!");
} else {
holder.titleTextView.setText(title);
}
}
@Override
public HeaderViewHolder createViewHolder(View view, FlexibleAdapter adapter) {
return new HeaderViewHolder(view, adapter);
}
static class HeaderViewHolder extends FlexibleViewHolder {
@BindView(R.id.title_text_view)
public TextView titleTextView;
/**
* Default constructor.
*/
HeaderViewHolder(View view, FlexibleAdapter adapter) {
super(view, adapter, true);
ButterKnife.bind(this, view);
}
}
}
}

View File

@ -38,103 +38,112 @@ import java.util.List;
import java.util.regex.Pattern;
public class MentionAutocompleteItem extends AbstractFlexibleItem<UserItem.UserItemViewHolder>
implements IFilterable<String> {
implements IFilterable<String> {
private String objectId;
private String displayName;
private String source;
private UserEntity currentUser;
private String objectId;
private String displayName;
private String source;
private UserEntity currentUser;
public MentionAutocompleteItem(String objectId, String displayName, String source, UserEntity currentUser) {
this.objectId = objectId;
this.displayName = displayName;
this.source = source;
this.currentUser = currentUser;
public MentionAutocompleteItem(String objectId, String displayName, String source,
UserEntity currentUser) {
this.objectId = objectId;
this.displayName = displayName;
this.source = source;
this.currentUser = currentUser;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public String getObjectId() {
return objectId;
}
public String getDisplayName() {
return displayName;
}
@Override
public boolean equals(Object o) {
if (o instanceof MentionAutocompleteItem) {
MentionAutocompleteItem inItem = (MentionAutocompleteItem) o;
return (objectId.equals(inItem.objectId) && displayName.equals(inItem.displayName));
}
public String getSource() {
return source;
return false;
}
@Override
public int getLayoutRes() {
return R.layout.rv_item_mention;
}
@Override
public UserItem.UserItemViewHolder createViewHolder(View view,
FlexibleAdapter<IFlexible> adapter) {
return new UserItem.UserItemViewHolder(view, adapter);
}
@SuppressLint("SetTextI18n")
@Override
public void bindViewHolder(FlexibleAdapter<IFlexible> adapter, UserItem.UserItemViewHolder holder,
int position, List<Object> payloads) {
if (adapter.hasFilter()) {
FlexibleUtils.highlightText(holder.contactDisplayName, displayName,
String.valueOf(adapter.getFilter(String.class)),
NextcloudTalkApplication.Companion.getSharedApplication()
.getResources().getColor(R.color.colorPrimary));
if (holder.contactMentionId != null) {
FlexibleUtils.highlightText(holder.contactMentionId, "@" + objectId,
String.valueOf(adapter.getFilter(String.class)),
NextcloudTalkApplication.Companion.getSharedApplication()
.getResources().getColor(R.color.colorPrimary));
}
} else {
holder.contactDisplayName.setText(displayName);
if (holder.contactMentionId != null) {
holder.contactMentionId.setText("@" + objectId);
}
}
public void setSource(String source) {
this.source = source;
if (source.equals("calls")) {
holder.simpleDraweeView.getHierarchy()
.setPlaceholderImage(DisplayUtils.getRoundedBitmapDrawableFromVectorDrawableResource(
NextcloudTalkApplication.Companion.getSharedApplication().getResources(),
R.drawable.ic_people_group_white_24px));
} else {
String avatarId = objectId;
String avatarUrl = ApiUtils.getUrlForAvatarWithName(currentUser.getBaseUrl(),
avatarId, R.dimen.avatar_size_big);
if (source.equals("guests")) {
avatarId = displayName;
avatarUrl = ApiUtils.getUrlForAvatarWithNameForGuests(currentUser.getBaseUrl(), avatarId,
R.dimen.avatar_size_big);
}
holder.simpleDraweeView.setController(null);
DraweeController draweeController = Fresco.newDraweeControllerBuilder()
.setOldController(holder.simpleDraweeView.getController())
.setAutoPlayAnimations(true)
.setImageRequest(DisplayUtils.getImageRequestForUrl(avatarUrl, null))
.build();
holder.simpleDraweeView.setController(draweeController);
}
}
public String getObjectId() {
return objectId;
}
public String getDisplayName() {
return displayName;
}
@Override
public boolean equals(Object o) {
if (o instanceof MentionAutocompleteItem) {
MentionAutocompleteItem inItem = (MentionAutocompleteItem) o;
return (objectId.equals(inItem.objectId) && displayName.equals(inItem.displayName));
}
return false;
}
@Override
public int getLayoutRes() {
return R.layout.rv_item_mention;
}
@Override
public UserItem.UserItemViewHolder createViewHolder(View view, FlexibleAdapter<IFlexible> adapter) {
return new UserItem.UserItemViewHolder(view, adapter);
}
@SuppressLint("SetTextI18n")
@Override
public void bindViewHolder(FlexibleAdapter<IFlexible> adapter, UserItem.UserItemViewHolder holder, int position, List<Object> payloads) {
if (adapter.hasFilter()) {
FlexibleUtils.highlightText(holder.contactDisplayName, displayName,
String.valueOf(adapter.getFilter(String.class)), NextcloudTalkApplication.Companion.getSharedApplication()
.getResources().getColor(R.color.colorPrimary));
if (holder.contactMentionId != null) {
FlexibleUtils.highlightText(holder.contactMentionId, "@" + objectId,
String.valueOf(adapter.getFilter(String.class)), NextcloudTalkApplication.Companion.getSharedApplication()
.getResources().getColor(R.color.colorPrimary));
}
} else {
holder.contactDisplayName.setText(displayName);
if (holder.contactMentionId != null) {
holder.contactMentionId.setText("@" + objectId);
}
}
if (source.equals("calls")) {
holder.simpleDraweeView.getHierarchy().setPlaceholderImage(DisplayUtils.getRoundedBitmapDrawableFromVectorDrawableResource(NextcloudTalkApplication.Companion.getSharedApplication().getResources(), R.drawable.ic_people_group_white_24px));
} else {
String avatarId = objectId;
String avatarUrl = ApiUtils.getUrlForAvatarWithName(currentUser.getBaseUrl(),
avatarId, R.dimen.avatar_size_big);
if (source.equals("guests")) {
avatarId = displayName;
avatarUrl = ApiUtils.getUrlForAvatarWithNameForGuests(currentUser.getBaseUrl(), avatarId, R.dimen.avatar_size_big);
}
holder.simpleDraweeView.setController(null);
DraweeController draweeController = Fresco.newDraweeControllerBuilder()
.setOldController(holder.simpleDraweeView.getController())
.setAutoPlayAnimations(true)
.setImageRequest(DisplayUtils.getImageRequestForUrl(avatarUrl, null))
.build();
holder.simpleDraweeView.setController(draweeController);
}
}
@Override
public boolean filter(String constraint) {
return objectId != null && Pattern.compile(constraint,
Pattern.CASE_INSENSITIVE | Pattern.LITERAL).matcher(objectId).find()
|| displayName != null && Pattern.compile(constraint, Pattern.CASE_INSENSITIVE | Pattern.LITERAL).matcher(displayName).find();
}
@Override
public boolean filter(String constraint) {
return objectId != null && Pattern.compile(constraint,
Pattern.CASE_INSENSITIVE | Pattern.LITERAL).matcher(objectId).find()
|| displayName != null && Pattern.compile(constraint,
Pattern.CASE_INSENSITIVE | Pattern.LITERAL).matcher(displayName).find();
}
}

View File

@ -39,69 +39,71 @@ import eu.davidea.viewholders.FlexibleViewHolder;
import java.util.List;
public class MenuItem extends AbstractFlexibleItem<MenuItem.MenuItemViewHolder> {
private String title;
private Drawable icon;
private int tag;
private int padding;
private String title;
private Drawable icon;
private int tag;
private int padding;
public MenuItem(String title, int tag, Drawable icon) {
this.title = title;
this.tag = tag;
this.icon = icon;
padding = (int) DisplayUtils.convertDpToPixel(16,
NextcloudTalkApplication.Companion.getSharedApplication().getApplicationContext());
public MenuItem(String title, int tag, Drawable icon) {
this.title = title;
this.tag = tag;
this.icon = icon;
padding = (int) DisplayUtils.convertDpToPixel(16,
NextcloudTalkApplication.Companion.getSharedApplication().getApplicationContext());
}
@Override
public boolean equals(Object o) {
if (o instanceof MenuItem) {
MenuItem inItem = (MenuItem) o;
return tag == inItem.tag;
}
return false;
}
@Override
public boolean equals(Object o) {
if (o instanceof MenuItem) {
MenuItem inItem = (MenuItem) o;
return tag == inItem.tag;
}
return false;
public int getTag() {
return tag;
}
@Override
public int getLayoutRes() {
return R.layout.rv_item_menu;
}
@Override
public MenuItem.MenuItemViewHolder createViewHolder(View view, FlexibleAdapter adapter) {
return new MenuItemViewHolder(view, adapter);
}
@Override
public void bindViewHolder(FlexibleAdapter adapter, MenuItem.MenuItemViewHolder holder,
int position, List payloads) {
if (position == 0) {
Spannable spannableString = new SpannableString(title);
spannableString.setSpan(
new ForegroundColorSpan(NextcloudTalkApplication.Companion.getSharedApplication()
.getResources().getColor(R.color.grey_600)), 0,
spannableString.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
holder.menuTitle.setText(spannableString);
} else {
holder.menuTitle.setText(title);
holder.menuTitle.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null);
holder.menuTitle.setCompoundDrawablePadding(padding);
}
}
public int getTag() {
return tag;
}
@Override
public int getLayoutRes() {
return R.layout.rv_item_menu;
}
@Override
public MenuItem.MenuItemViewHolder createViewHolder(View view, FlexibleAdapter adapter) {
return new MenuItemViewHolder(view, adapter);
}
@Override
public void bindViewHolder(FlexibleAdapter adapter, MenuItem.MenuItemViewHolder holder, int position, List payloads) {
if (position == 0) {
Spannable spannableString = new SpannableString(title);
spannableString.setSpan(new ForegroundColorSpan(NextcloudTalkApplication.Companion.getSharedApplication()
.getResources().getColor(R.color.grey_600)), 0,
spannableString.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
holder.menuTitle.setText(spannableString);
} else {
holder.menuTitle.setText(title);
holder.menuTitle.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null);
holder.menuTitle.setCompoundDrawablePadding(padding);
}
}
static class MenuItemViewHolder extends FlexibleViewHolder {
@BindView(R.id.menu_text)
public TextView menuTitle;
/**
* Default constructor.
*/
MenuItemViewHolder(View view, FlexibleAdapter adapter) {
super(view, adapter);
ButterKnife.bind(this, view);
}
static class MenuItemViewHolder extends FlexibleViewHolder {
@BindView(R.id.menu_text)
public TextView menuTitle;
/**
* Default constructor.
*/
MenuItemViewHolder(View view, FlexibleAdapter adapter) {
super(view, adapter);
ButterKnife.bind(this, view);
}
}
}

View File

@ -36,76 +36,80 @@ import eu.davidea.flexibleadapter.items.IFlexible;
import eu.davidea.viewholders.FlexibleViewHolder;
import java.util.List;
public class NotificationSoundItem extends AbstractFlexibleItem<NotificationSoundItem.NotificationSoundItemViewHolder> {
public class NotificationSoundItem
extends AbstractFlexibleItem<NotificationSoundItem.NotificationSoundItemViewHolder> {
private String notificationSoundName;
private String notificationSoundUri;
private String notificationSoundName;
private String notificationSoundUri;
public NotificationSoundItem(String notificationSoundName, String notificationSoundUri) {
this.notificationSoundName = notificationSoundName;
this.notificationSoundUri = notificationSoundUri;
public NotificationSoundItem(String notificationSoundName, String notificationSoundUri) {
this.notificationSoundName = notificationSoundName;
this.notificationSoundUri = notificationSoundUri;
}
public String getNotificationSoundUri() {
return notificationSoundUri;
}
public String getNotificationSoundName() {
return notificationSoundName;
}
@Override
public boolean equals(Object o) {
return false;
}
@Override
public int getLayoutRes() {
return R.layout.rv_item_notification_sound;
}
@Override
public NotificationSoundItemViewHolder createViewHolder(View view,
FlexibleAdapter<IFlexible> adapter) {
return new NotificationSoundItemViewHolder(view, adapter);
}
@Override
public void bindViewHolder(FlexibleAdapter<IFlexible> adapter,
NotificationSoundItemViewHolder holder, int position, List<Object> payloads) {
holder.notificationName.setText(notificationSoundName);
if (adapter.isSelected(position)) {
holder.checkedImageView.setVisibility(View.VISIBLE);
} else {
holder.checkedImageView.setVisibility(View.GONE);
}
public String getNotificationSoundUri() {
return notificationSoundUri;
Resources resources = NextcloudTalkApplication.Companion.getSharedApplication().getResources();
holder.simpleDraweeView.getHierarchy()
.setBackgroundImage(new ColorDrawable(resources.getColor(R.color.colorPrimary)));
if (position == 0) {
holder.simpleDraweeView.getHierarchy()
.setImage(resources.getDrawable(R.drawable.ic_stop_white_24dp), 100,
true);
} else {
holder.simpleDraweeView.getHierarchy()
.setImage(resources.getDrawable(R.drawable.ic_play_circle_outline_white_24dp), 100,
true);
}
}
public String getNotificationSoundName() {
return notificationSoundName;
static class NotificationSoundItemViewHolder extends FlexibleViewHolder {
@BindView(R.id.notificationNameTextView)
public TextView notificationName;
@BindView(R.id.simpleDraweeView)
SimpleDraweeView simpleDraweeView;
@BindView(R.id.checkedImageView)
ImageView checkedImageView;
/**
* Default constructor.
*/
NotificationSoundItemViewHolder(View view, FlexibleAdapter adapter) {
super(view, adapter);
ButterKnife.bind(this, view);
}
@Override
public boolean equals(Object o) {
return false;
}
@Override
public int getLayoutRes() {
return R.layout.rv_item_notification_sound;
}
@Override
public NotificationSoundItemViewHolder createViewHolder(View view, FlexibleAdapter<IFlexible> adapter) {
return new NotificationSoundItemViewHolder(view, adapter);
}
@Override
public void bindViewHolder(FlexibleAdapter<IFlexible> adapter, NotificationSoundItemViewHolder holder, int position, List<Object> payloads) {
holder.notificationName.setText(notificationSoundName);
if (adapter.isSelected(position)) {
holder.checkedImageView.setVisibility(View.VISIBLE);
} else {
holder.checkedImageView.setVisibility(View.GONE);
}
Resources resources = NextcloudTalkApplication.Companion.getSharedApplication().getResources();
holder.simpleDraweeView.getHierarchy().setBackgroundImage(new ColorDrawable(resources.getColor(R.color.colorPrimary)));
if (position == 0) {
holder.simpleDraweeView.getHierarchy().setImage(resources.getDrawable(R.drawable.ic_stop_white_24dp), 100,
true);
} else {
holder.simpleDraweeView.getHierarchy().setImage(resources.getDrawable(R.drawable.ic_play_circle_outline_white_24dp), 100,
true);
}
}
static class NotificationSoundItemViewHolder extends FlexibleViewHolder {
@BindView(R.id.notificationNameTextView)
public TextView notificationName;
@BindView(R.id.simpleDraweeView)
SimpleDraweeView simpleDraweeView;
@BindView(R.id.checkedImageView)
ImageView checkedImageView;
/**
* Default constructor.
*/
NotificationSoundItemViewHolder(View view, FlexibleAdapter adapter) {
super(view, adapter);
ButterKnife.bind(this, view);
}
}
}
}

View File

@ -47,95 +47,95 @@ import java.util.List;
*/
public class ProgressItem extends AbstractFlexibleItem<ProgressItem.ProgressViewHolder> {
private StatusEnum status = StatusEnum.MORE_TO_LOAD;
private StatusEnum status = StatusEnum.MORE_TO_LOAD;
@Override
public boolean equals(Object o) {
return this == o;//The default implementation
@Override
public boolean equals(Object o) {
return this == o;//The default implementation
}
public StatusEnum getStatus() {
return status;
}
public void setStatus(StatusEnum status) {
this.status = status;
}
@Override
public int getLayoutRes() {
return R.layout.rv_item_progress;
}
@Override
public void bindViewHolder(FlexibleAdapter<IFlexible> adapter, ProgressViewHolder holder,
int position, List<Object> payloads) {
Context context = holder.itemView.getContext();
holder.progressBar.setVisibility(View.GONE);
holder.progressMessage.setVisibility(View.VISIBLE);
if (!adapter.isEndlessScrollEnabled()) {
setStatus(StatusEnum.DISABLE_ENDLESS);
} else if (payloads.contains(Payload.NO_MORE_LOAD)) {
setStatus(StatusEnum.NO_MORE_LOAD);
}
public StatusEnum getStatus() {
return status;
switch (this.status) {
case NO_MORE_LOAD:
holder.progressMessage.setText(
context.getString(R.string.nc_no_more_load_retry));
// Reset to default status for next binding
setStatus(StatusEnum.MORE_TO_LOAD);
break;
case DISABLE_ENDLESS:
holder.progressMessage.setText(context.getString(R.string.nc_endless_disabled));
break;
case ON_CANCEL:
holder.progressMessage.setText(context.getString(R.string.nc_endless_cancel));
// Reset to default status for next binding
setStatus(StatusEnum.MORE_TO_LOAD);
break;
case ON_ERROR:
holder.progressMessage.setText(context.getString(R.string.nc_endless_error));
// Reset to default status for next binding
setStatus(StatusEnum.MORE_TO_LOAD);
break;
default:
holder.progressBar.setVisibility(View.VISIBLE);
holder.progressMessage.setVisibility(View.GONE);
break;
}
}
public void setStatus(StatusEnum status) {
this.status = status;
@Override
public ProgressViewHolder createViewHolder(View view, FlexibleAdapter adapter) {
return new ProgressViewHolder(view, adapter);
}
public enum StatusEnum {
MORE_TO_LOAD, //Default = should have an empty Payload
DISABLE_ENDLESS, //Endless is disabled because user has set limits
NO_MORE_LOAD, //Non-empty Payload = Payload.NO_MORE_LOAD
ON_CANCEL,
ON_ERROR
}
static class ProgressViewHolder extends FlexibleViewHolder {
@BindView(R.id.progress_bar)
ProgressBar progressBar;
@BindView(R.id.progress_message)
TextView progressMessage;
ProgressViewHolder(View view, FlexibleAdapter adapter) {
super(view, adapter);
ButterKnife.bind(this, view);
}
@Override
public int getLayoutRes() {
return R.layout.rv_item_progress;
public void scrollAnimators(@NonNull List<Animator> animators, int position,
boolean isForward) {
AnimatorHelper.scaleAnimator(animators, itemView, 0f);
}
@Override
public void bindViewHolder(FlexibleAdapter<IFlexible> adapter, ProgressViewHolder holder, int position, List<Object> payloads) {
Context context = holder.itemView.getContext();
holder.progressBar.setVisibility(View.GONE);
holder.progressMessage.setVisibility(View.VISIBLE);
if (!adapter.isEndlessScrollEnabled()) {
setStatus(StatusEnum.DISABLE_ENDLESS);
} else if (payloads.contains(Payload.NO_MORE_LOAD)) {
setStatus(StatusEnum.NO_MORE_LOAD);
}
switch (this.status) {
case NO_MORE_LOAD:
holder.progressMessage.setText(
context.getString(R.string.nc_no_more_load_retry));
// Reset to default status for next binding
setStatus(StatusEnum.MORE_TO_LOAD);
break;
case DISABLE_ENDLESS:
holder.progressMessage.setText(context.getString(R.string.nc_endless_disabled));
break;
case ON_CANCEL:
holder.progressMessage.setText(context.getString(R.string.nc_endless_cancel));
// Reset to default status for next binding
setStatus(StatusEnum.MORE_TO_LOAD);
break;
case ON_ERROR:
holder.progressMessage.setText(context.getString(R.string.nc_endless_error));
// Reset to default status for next binding
setStatus(StatusEnum.MORE_TO_LOAD);
break;
default:
holder.progressBar.setVisibility(View.VISIBLE);
holder.progressMessage.setVisibility(View.GONE);
break;
}
}
@Override
public ProgressViewHolder createViewHolder(View view, FlexibleAdapter adapter) {
return new ProgressViewHolder(view, adapter);
}
public enum StatusEnum {
MORE_TO_LOAD, //Default = should have an empty Payload
DISABLE_ENDLESS, //Endless is disabled because user has set limits
NO_MORE_LOAD, //Non-empty Payload = Payload.NO_MORE_LOAD
ON_CANCEL,
ON_ERROR
}
static class ProgressViewHolder extends FlexibleViewHolder {
@BindView(R.id.progress_bar)
ProgressBar progressBar;
@BindView(R.id.progress_message)
TextView progressMessage;
ProgressViewHolder(View view, FlexibleAdapter adapter) {
super(view, adapter);
ButterKnife.bind(this, view);
}
@Override
public void scrollAnimators(@NonNull List<Animator> animators, int position, boolean isForward) {
AnimatorHelper.scaleAnimator(animators, itemView, 0f);
}
}
}
}

View File

@ -50,248 +50,266 @@ import java.util.regex.Pattern;
import javax.annotation.Nullable;
public class UserItem extends AbstractFlexibleItem<UserItem.UserItemViewHolder> implements
ISectionable<UserItem.UserItemViewHolder, GenericTextHeaderItem>, IFilterable<String> {
ISectionable<UserItem.UserItemViewHolder, GenericTextHeaderItem>, IFilterable<String> {
private Participant participant;
private UserEntity userEntity;
private GenericTextHeaderItem header;
private Context activityContext;
public boolean isOnline = true;
public boolean isOnline = true;
private Participant participant;
private UserEntity userEntity;
private GenericTextHeaderItem header;
private Context activityContext;
public UserItem(Participant participant, UserEntity userEntity,
GenericTextHeaderItem genericTextHeaderItem, Context activityContext) {
this.participant = participant;
this.userEntity = userEntity;
this.header = genericTextHeaderItem;
this.activityContext = activityContext;
public UserItem(Participant participant, UserEntity userEntity,
GenericTextHeaderItem genericTextHeaderItem, Context activityContext) {
this.participant = participant;
this.userEntity = userEntity;
this.header = genericTextHeaderItem;
this.activityContext = activityContext;
}
@Override
public boolean equals(Object o) {
if (o instanceof UserItem) {
UserItem inItem = (UserItem) o;
return participant.getUserId().equals(inItem.getModel().getUserId());
}
return false;
}
@Override
public int hashCode() {
return participant.hashCode();
}
/**
* @return the model object
*/
public Participant getModel() {
return participant;
}
public UserEntity getEntity() {
return userEntity;
}
@Override
public int getLayoutRes() {
if (header != null) {
return R.layout.rv_item_contact;
} else {
return R.layout.rv_item_conversation_info_participant;
}
}
@Override
public UserItemViewHolder createViewHolder(View view, FlexibleAdapter adapter) {
return new UserItemViewHolder(view, adapter);
}
@Override
public void bindViewHolder(FlexibleAdapter adapter, UserItemViewHolder holder, int position,
List payloads) {
holder.simpleDraweeView.setController(null);
if (holder.checkedImageView != null) {
if (participant.isSelected()) {
holder.checkedImageView.setVisibility(View.VISIBLE);
} else {
holder.checkedImageView.setVisibility(View.GONE);
}
}
@Override
public boolean equals(Object o) {
if (o instanceof UserItem) {
UserItem inItem = (UserItem) o;
return participant.getUserId().equals(inItem.getModel().getUserId());
if (!isOnline) {
if (holder.contactMentionId != null) {
holder.contactMentionId.setAlpha(0.38f);
}
holder.contactDisplayName.setAlpha(0.38f);
holder.simpleDraweeView.setAlpha(0.38f);
} else {
if (holder.contactMentionId != null) {
holder.contactMentionId.setAlpha(1.0f);
}
holder.contactDisplayName.setAlpha(1.0f);
holder.simpleDraweeView.setAlpha(1.0f);
}
if (adapter.hasFilter()) {
FlexibleUtils.highlightText(holder.contactDisplayName, participant.getDisplayName(),
String.valueOf(adapter.getFilter(String.class)),
activityContext.getResources().getColor(R.color.colorPrimary));
}
holder.contactDisplayName.setText(participant.getDisplayName());
if (TextUtils.isEmpty(participant.getDisplayName()) &&
(participant.getType().equals(Participant.ParticipantType.GUEST) || participant.getType()
.equals(Participant.ParticipantType.USER_FOLLOWING_LINK))) {
holder.contactDisplayName.setText(
NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest));
}
if (TextUtils.isEmpty(participant.getSource()) || participant.getSource().equals("users")) {
if (Participant.ParticipantType.GUEST.equals(participant.getType()) ||
Participant.ParticipantType.USER_FOLLOWING_LINK.equals(participant.getType())) {
String displayName = NextcloudTalkApplication.Companion.getSharedApplication()
.getResources()
.getString(R.string.nc_guest);
if (!TextUtils.isEmpty(participant.getDisplayName())) {
displayName = participant.getDisplayName();
}
return false;
DraweeController draweeController = Fresco.newDraweeControllerBuilder()
.setOldController(holder.simpleDraweeView.getController())
.setAutoPlayAnimations(true)
.setImageRequest(DisplayUtils.getImageRequestForUrl(
ApiUtils.getUrlForAvatarWithNameForGuests(userEntity.getBaseUrl(),
displayName, R.dimen.avatar_size), null))
.build();
holder.simpleDraweeView.setController(draweeController);
} else {
DraweeController draweeController = Fresco.newDraweeControllerBuilder()
.setOldController(holder.simpleDraweeView.getController())
.setAutoPlayAnimations(true)
.setImageRequest(DisplayUtils.getImageRequestForUrl(
ApiUtils.getUrlForAvatarWithName(userEntity.getBaseUrl(),
participant.getUserId(), R.dimen.avatar_size), null))
.build();
holder.simpleDraweeView.setController(draweeController);
}
} else if ("groups".equals(participant.getSource())) {
holder.simpleDraweeView.getHierarchy()
.setImage(new BitmapDrawable(DisplayUtils.getRoundedBitmapFromVectorDrawableResource(
activityContext.getResources(), R.drawable.ic_people_group_white_24px)), 100, true);
}
@Override
public int hashCode() {
return participant.hashCode();
Resources resources = activityContext.getResources();
if (header == null) {
Participant.ParticipantFlags participantFlags = participant.getParticipantFlags();
switch (participantFlags) {
case NOT_IN_CALL:
holder.voiceOrSimpleCallImageView.setVisibility(View.GONE);
holder.videoCallImageView.setVisibility(View.GONE);
break;
case IN_CALL:
holder.voiceOrSimpleCallImageView.setBackground(
resources.getDrawable(R.drawable.shape_call_bubble));
holder.voiceOrSimpleCallImageView.setVisibility(View.VISIBLE);
holder.videoCallImageView.setVisibility(View.GONE);
break;
case IN_CALL_WITH_AUDIO:
holder.voiceOrSimpleCallImageView.setBackground(
resources.getDrawable(R.drawable.shape_voice_bubble));
holder.voiceOrSimpleCallImageView.setVisibility(View.VISIBLE);
holder.videoCallImageView.setVisibility(View.GONE);
break;
case IN_CALL_WITH_VIDEO:
holder.voiceOrSimpleCallImageView.setBackground(
resources.getDrawable(R.drawable.shape_call_bubble));
holder.videoCallImageView.setBackground(
resources.getDrawable(R.drawable.shape_video_bubble));
holder.voiceOrSimpleCallImageView.setVisibility(View.VISIBLE);
holder.videoCallImageView.setVisibility(View.VISIBLE);
break;
case IN_CALL_WITH_AUDIO_AND_VIDEO:
holder.voiceOrSimpleCallImageView.setBackground(
resources.getDrawable(R.drawable.shape_voice_bubble));
holder.videoCallImageView.setBackground(
resources.getDrawable(R.drawable.shape_video_bubble));
holder.voiceOrSimpleCallImageView.setVisibility(View.VISIBLE);
holder.videoCallImageView.setVisibility(View.VISIBLE);
break;
default:
holder.voiceOrSimpleCallImageView.setVisibility(View.GONE);
holder.videoCallImageView.setVisibility(View.GONE);
break;
}
if (holder.contactMentionId != null) {
String userType = "";
switch (new EnumParticipantTypeConverter().convertToInt(participant.getType())) {
case 1:
//userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_owner);
//break;
case 2:
userType = NextcloudTalkApplication.Companion.getSharedApplication()
.getString(R.string.nc_moderator);
break;
case 3:
userType = NextcloudTalkApplication.Companion.getSharedApplication()
.getString(R.string.nc_user);
break;
case 4:
userType = NextcloudTalkApplication.Companion.getSharedApplication()
.getString(R.string.nc_guest);
break;
case 5:
userType = NextcloudTalkApplication.Companion.getSharedApplication()
.getString(R.string.nc_following_link);
break;
default:
break;
}
if (!holder.contactMentionId.getText().equals(userType)) {
holder.contactMentionId.setText(userType);
holder.contactMentionId.setTextColor(
activityContext.getResources().getColor(R.color.colorPrimary));
}
}
}
}
@Override
public boolean filter(String constraint) {
return participant.getDisplayName() != null &&
(Pattern.compile(constraint, Pattern.CASE_INSENSITIVE | Pattern.LITERAL)
.matcher(participant.getDisplayName().trim())
.find() ||
Pattern.compile(constraint, Pattern.CASE_INSENSITIVE | Pattern.LITERAL)
.matcher(participant.getUserId().trim())
.find());
}
@Override
public GenericTextHeaderItem getHeader() {
return header;
}
@Override
public void setHeader(GenericTextHeaderItem header) {
this.header = header;
}
static class UserItemViewHolder extends FlexibleViewHolder {
@BindView(R.id.name_text)
public EmojiTextView contactDisplayName;
@BindView(R.id.simple_drawee_view)
public SimpleDraweeView simpleDraweeView;
@Nullable
@BindView(R.id.secondary_text)
public EmojiTextView contactMentionId;
@Nullable
@BindView(R.id.voiceOrSimpleCallImageView)
ImageView voiceOrSimpleCallImageView;
@Nullable
@BindView(R.id.videoCallImageView)
ImageView videoCallImageView;
@Nullable
@BindView(R.id.checkedImageView)
ImageView checkedImageView;
/**
* @return the model object
* Default constructor.
*/
public Participant getModel() {
return participant;
UserItemViewHolder(View view, FlexibleAdapter adapter) {
super(view, adapter);
ButterKnife.bind(this, view);
}
public UserEntity getEntity() {
return userEntity;
}
@Override
public int getLayoutRes() {
if (header != null) {
return R.layout.rv_item_contact;
} else {
return R.layout.rv_item_conversation_info_participant;
}
}
@Override
public UserItemViewHolder createViewHolder(View view, FlexibleAdapter adapter) {
return new UserItemViewHolder(view, adapter);
}
@Override
public void bindViewHolder(FlexibleAdapter adapter, UserItemViewHolder holder, int position, List payloads) {
holder.simpleDraweeView.setController(null);
if (holder.checkedImageView != null) {
if (participant.isSelected()) {
holder.checkedImageView.setVisibility(View.VISIBLE);
} else {
holder.checkedImageView.setVisibility(View.GONE);
}
}
if (!isOnline) {
if (holder.contactMentionId != null) {
holder.contactMentionId.setAlpha(0.38f);
}
holder.contactDisplayName.setAlpha(0.38f);
holder.simpleDraweeView.setAlpha(0.38f);
} else {
if (holder.contactMentionId != null) {
holder.contactMentionId.setAlpha(1.0f);
}
holder.contactDisplayName.setAlpha(1.0f);
holder.simpleDraweeView.setAlpha(1.0f);
}
if (adapter.hasFilter()) {
FlexibleUtils.highlightText(holder.contactDisplayName, participant.getDisplayName(),
String.valueOf(adapter.getFilter(String.class)), activityContext.getResources().getColor(R.color.colorPrimary));
}
holder.contactDisplayName.setText(participant.getDisplayName());
if (TextUtils.isEmpty(participant.getDisplayName()) &&
(participant.getType().equals(Participant.ParticipantType.GUEST) || participant.getType().equals(Participant.ParticipantType.USER_FOLLOWING_LINK))) {
holder.contactDisplayName.setText(NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest));
}
if (TextUtils.isEmpty(participant.getSource()) || participant.getSource().equals("users")) {
if (Participant.ParticipantType.GUEST.equals(participant.getType()) ||
Participant.ParticipantType.USER_FOLLOWING_LINK.equals(participant.getType())) {
String displayName = NextcloudTalkApplication.Companion.getSharedApplication().getResources().getString(R.string.nc_guest);
if (!TextUtils.isEmpty(participant.getDisplayName())) {
displayName = participant.getDisplayName();
}
DraweeController draweeController = Fresco.newDraweeControllerBuilder()
.setOldController(holder.simpleDraweeView.getController())
.setAutoPlayAnimations(true)
.setImageRequest(DisplayUtils.getImageRequestForUrl(ApiUtils.getUrlForAvatarWithNameForGuests(userEntity.getBaseUrl(),
displayName, R.dimen.avatar_size), null))
.build();
holder.simpleDraweeView.setController(draweeController);
} else {
DraweeController draweeController = Fresco.newDraweeControllerBuilder()
.setOldController(holder.simpleDraweeView.getController())
.setAutoPlayAnimations(true)
.setImageRequest(DisplayUtils.getImageRequestForUrl(ApiUtils.getUrlForAvatarWithName(userEntity.getBaseUrl(),
participant.getUserId(), R.dimen.avatar_size), null))
.build();
holder.simpleDraweeView.setController(draweeController);
}
} else if ("groups".equals(participant.getSource())) {
holder.simpleDraweeView.getHierarchy().setImage(new BitmapDrawable(DisplayUtils.getRoundedBitmapFromVectorDrawableResource(activityContext.getResources(), R.drawable.ic_people_group_white_24px)), 100, true);
}
Resources resources = activityContext.getResources();
if (header == null) {
Participant.ParticipantFlags participantFlags = participant.getParticipantFlags();
switch (participantFlags) {
case NOT_IN_CALL:
holder.voiceOrSimpleCallImageView.setVisibility(View.GONE);
holder.videoCallImageView.setVisibility(View.GONE);
break;
case IN_CALL:
holder.voiceOrSimpleCallImageView.setBackground(resources.getDrawable(R.drawable.shape_call_bubble));
holder.voiceOrSimpleCallImageView.setVisibility(View.VISIBLE);
holder.videoCallImageView.setVisibility(View.GONE);
break;
case IN_CALL_WITH_AUDIO:
holder.voiceOrSimpleCallImageView.setBackground(resources.getDrawable(R.drawable.shape_voice_bubble));
holder.voiceOrSimpleCallImageView.setVisibility(View.VISIBLE);
holder.videoCallImageView.setVisibility(View.GONE);
break;
case IN_CALL_WITH_VIDEO:
holder.voiceOrSimpleCallImageView.setBackground(resources.getDrawable(R.drawable.shape_call_bubble));
holder.videoCallImageView.setBackground(resources.getDrawable(R.drawable.shape_video_bubble));
holder.voiceOrSimpleCallImageView.setVisibility(View.VISIBLE);
holder.videoCallImageView.setVisibility(View.VISIBLE);
break;
case IN_CALL_WITH_AUDIO_AND_VIDEO:
holder.voiceOrSimpleCallImageView.setBackground(resources.getDrawable(R.drawable.shape_voice_bubble));
holder.videoCallImageView.setBackground(resources.getDrawable(R.drawable.shape_video_bubble));
holder.voiceOrSimpleCallImageView.setVisibility(View.VISIBLE);
holder.videoCallImageView.setVisibility(View.VISIBLE);
break;
default:
holder.voiceOrSimpleCallImageView.setVisibility(View.GONE);
holder.videoCallImageView.setVisibility(View.GONE);
break;
}
if (holder.contactMentionId != null) {
String userType = "";
switch (new EnumParticipantTypeConverter().convertToInt(participant.getType())) {
case 1:
//userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_owner);
//break;
case 2:
userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_moderator);
break;
case 3:
userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_user);
break;
case 4:
userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest);
break;
case 5:
userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_following_link);
break;
default:
break;
}
if (!holder.contactMentionId.getText().equals(userType)) {
holder.contactMentionId.setText(userType);
holder.contactMentionId.setTextColor(activityContext.getResources().getColor(R.color.colorPrimary));
}
}
}
}
@Override
public boolean filter(String constraint) {
return participant.getDisplayName() != null &&
(Pattern.compile(constraint, Pattern.CASE_INSENSITIVE | Pattern.LITERAL).matcher(participant.getDisplayName().trim()).find() ||
Pattern.compile(constraint, Pattern.CASE_INSENSITIVE | Pattern.LITERAL).matcher(participant.getUserId().trim()).find());
}
@Override
public GenericTextHeaderItem getHeader() {
return header;
}
@Override
public void setHeader(GenericTextHeaderItem header) {
this.header = header;
}
static class UserItemViewHolder extends FlexibleViewHolder {
@BindView(R.id.name_text)
public EmojiTextView contactDisplayName;
@BindView(R.id.simple_drawee_view)
public SimpleDraweeView simpleDraweeView;
@Nullable
@BindView(R.id.secondary_text)
public EmojiTextView contactMentionId;
@Nullable
@BindView(R.id.voiceOrSimpleCallImageView)
ImageView voiceOrSimpleCallImageView;
@Nullable
@BindView(R.id.videoCallImageView)
ImageView videoCallImageView;
@Nullable
@BindView(R.id.checkedImageView)
ImageView checkedImageView;
/**
* Default constructor.
*/
UserItemViewHolder(View view, FlexibleAdapter adapter) {
super(view, adapter);
ButterKnife.bind(this, view);
}
}
}
}

View File

@ -54,150 +54,154 @@ import javax.inject.Inject;
@AutoInjector(NextcloudTalkApplication.class)
public class MagicIncomingTextMessageViewHolder
extends MessageHolders.IncomingTextMessageViewHolder<ChatMessage> {
extends MessageHolders.IncomingTextMessageViewHolder<ChatMessage> {
@BindView(R.id.messageAuthor)
EmojiTextView messageAuthor;
@BindView(R.id.messageAuthor)
EmojiTextView messageAuthor;
@BindView(R.id.messageText)
EmojiTextView messageText;
@BindView(R.id.messageText)
EmojiTextView messageText;
@BindView(R.id.messageUserAvatar)
SimpleDraweeView messageUserAvatarView;
@BindView(R.id.messageUserAvatar)
SimpleDraweeView messageUserAvatarView;
@BindView(R.id.messageTime)
TextView messageTimeView;
@BindView(R.id.messageTime)
TextView messageTimeView;
@Inject
UserUtils userUtils;
@Inject
UserUtils userUtils;
@Inject
Context context;
@Inject
Context context;
@Inject
AppPreferences appPreferences;
@Inject
AppPreferences appPreferences;
private View itemView;
private View itemView;
public MagicIncomingTextMessageViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
public MagicIncomingTextMessageViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
NextcloudTalkApplication.Companion.getSharedApplication()
.getComponentApplication()
.inject(this);
this.itemView = itemView;
this.itemView = itemView;
}
@Override
public void onBind(ChatMessage message) {
super.onBind(message);
String author;
if (!TextUtils.isEmpty(author = message.getActorDisplayName())) {
messageAuthor.setText(author);
} else {
messageAuthor.setText(R.string.nc_nick_guest);
}
if (!message.isGrouped() && !message.isOneToOneConversation()) {
messageUserAvatarView.setVisibility(View.VISIBLE);
if (message.getActorType().equals("guests")) {
// do nothing, avatar is set
} else if (message.getActorType().equals("bots") && message.getActorId()
.equals("changelog")) {
messageUserAvatarView.setController(null);
Drawable[] layers = new Drawable[2];
layers[0] = context.getDrawable(R.drawable.ic_launcher_background);
layers[1] = context.getDrawable(R.drawable.ic_launcher_foreground);
LayerDrawable layerDrawable = new LayerDrawable(layers);
@Override
public void onBind(ChatMessage message) {
super.onBind(message);
String author;
messageUserAvatarView.getHierarchy()
.setPlaceholderImage(DisplayUtils.getRoundedDrawable(layerDrawable));
} else if (message.getActorType().equals("bots")) {
messageUserAvatarView.setController(null);
TextDrawable drawable =
TextDrawable.builder().beginConfig().bold().endConfig().buildRound(">",
context.getResources().getColor(R.color.black));
messageUserAvatarView.setVisibility(View.VISIBLE);
messageUserAvatarView.getHierarchy().setPlaceholderImage(drawable);
}
} else {
if (message.isOneToOneConversation()) {
messageUserAvatarView.setVisibility(View.GONE);
} else {
messageUserAvatarView.setVisibility(View.INVISIBLE);
}
messageAuthor.setVisibility(View.GONE);
}
if (!TextUtils.isEmpty(author = message.getActorDisplayName())) {
messageAuthor.setText(author);
} else {
messageAuthor.setText(R.string.nc_nick_guest);
}
Resources resources = itemView.getResources();
if (!message.isGrouped() && !message.isOneToOneConversation()) {
messageUserAvatarView.setVisibility(View.VISIBLE);
if (message.getActorType().equals("guests")) {
// do nothing, avatar is set
} else if (message.getActorType().equals("bots") && message.getActorId().equals("changelog")) {
messageUserAvatarView.setController(null);
Drawable[] layers = new Drawable[2];
layers[0] = context.getDrawable(R.drawable.ic_launcher_background);
layers[1] = context.getDrawable(R.drawable.ic_launcher_foreground);
LayerDrawable layerDrawable = new LayerDrawable(layers);
int bg_bubble_color = resources.getColor(R.color.bg_message_list_incoming_bubble);
messageUserAvatarView.getHierarchy().setPlaceholderImage(DisplayUtils.getRoundedDrawable(layerDrawable));
} else if (message.getActorType().equals("bots")) {
messageUserAvatarView.setController(null);
TextDrawable drawable = TextDrawable.builder().beginConfig().bold().endConfig().buildRound(">",
context.getResources().getColor(R.color.black));
messageUserAvatarView.setVisibility(View.VISIBLE);
messageUserAvatarView.getHierarchy().setPlaceholderImage(drawable);
}
} else {
if (message.isOneToOneConversation()) {
messageUserAvatarView.setVisibility(View.GONE);
int bubbleResource = R.drawable.shape_incoming_message;
if (message.isGrouped) {
bubbleResource = R.drawable.shape_grouped_incoming_message;
}
Drawable bubbleDrawable = DisplayUtils.getMessageSelector(bg_bubble_color,
resources.getColor(R.color.transparent),
bg_bubble_color, bubbleResource);
ViewCompat.setBackground(bubble, bubbleDrawable);
HashMap<String, HashMap<String, String>> messageParameters = message.getMessageParameters();
itemView.setSelected(false);
messageTimeView.setTextColor(context.getResources().getColor(R.color.warm_grey_four));
FlexboxLayout.LayoutParams layoutParams =
(FlexboxLayout.LayoutParams) messageTimeView.getLayoutParams();
layoutParams.setWrapBefore(false);
Spannable messageString = new SpannableString(message.getText());
float textSize = context.getResources().getDimension(R.dimen.chat_text_size);
if (messageParameters != null && messageParameters.size() > 0) {
for (String key : messageParameters.keySet()) {
Map<String, String> individualHashMap = message.getMessageParameters().get(key);
if (individualHashMap != null) {
if (individualHashMap.get("type").equals("user") || individualHashMap.get("type")
.equals("guest") || individualHashMap.get("type").equals("call")) {
if (individualHashMap.get("id").equals(message.getActiveUser().getUserId())) {
messageString =
DisplayUtils.searchAndReplaceWithMentionSpan(messageText.getContext(),
messageString,
individualHashMap.get("id"),
individualHashMap.get("name"),
individualHashMap.get("type"),
userUtils.getUserById(message.getActiveUser().getUserId()),
R.xml.chip_you);
} else {
messageUserAvatarView.setVisibility(View.INVISIBLE);
messageString =
DisplayUtils.searchAndReplaceWithMentionSpan(messageText.getContext(),
messageString,
individualHashMap.get("id"),
individualHashMap.get("name"),
individualHashMap.get("type"),
userUtils.getUserById(message.getActiveUser().getUserId()),
R.xml.chip_others);
}
messageAuthor.setVisibility(View.GONE);
} else if (individualHashMap.get("type").equals("file")) {
itemView.setOnClickListener(v -> {
Intent browserIntent =
new Intent(Intent.ACTION_VIEW, Uri.parse(individualHashMap.get("link")));
context.startActivity(browserIntent);
});
}
}
Resources resources = itemView.getResources();
int bg_bubble_color = resources.getColor(R.color.bg_message_list_incoming_bubble);
int bubbleResource = R.drawable.shape_incoming_message;
if (message.isGrouped) {
bubbleResource = R.drawable.shape_grouped_incoming_message;
}
Drawable bubbleDrawable = DisplayUtils.getMessageSelector(bg_bubble_color,
resources.getColor(R.color.transparent),
bg_bubble_color, bubbleResource);
ViewCompat.setBackground(bubble, bubbleDrawable);
HashMap<String, HashMap<String, String>> messageParameters = message.getMessageParameters();
itemView.setSelected(false);
messageTimeView.setTextColor(context.getResources().getColor(R.color.warm_grey_four));
FlexboxLayout.LayoutParams layoutParams = (FlexboxLayout.LayoutParams) messageTimeView.getLayoutParams();
layoutParams.setWrapBefore(false);
Spannable messageString = new SpannableString(message.getText());
float textSize = context.getResources().getDimension(R.dimen.chat_text_size);
if (messageParameters != null && messageParameters.size() > 0) {
for (String key : messageParameters.keySet()) {
Map<String, String> individualHashMap = message.getMessageParameters().get(key);
if (individualHashMap != null) {
if (individualHashMap.get("type").equals("user") || individualHashMap.get("type").equals("guest") || individualHashMap.get("type").equals("call")) {
if (individualHashMap.get("id").equals(message.getActiveUser().getUserId())) {
messageString =
DisplayUtils.searchAndReplaceWithMentionSpan(messageText.getContext(),
messageString,
individualHashMap.get("id"),
individualHashMap.get("name"),
individualHashMap.get("type"),
userUtils.getUserById(message.getActiveUser().getUserId()),
R.xml.chip_you);
} else {
messageString =
DisplayUtils.searchAndReplaceWithMentionSpan(messageText.getContext(),
messageString,
individualHashMap.get("id"),
individualHashMap.get("name"),
individualHashMap.get("type"),
userUtils.getUserById(message.getActiveUser().getUserId()),
R.xml.chip_others);
}
} else if (individualHashMap.get("type").equals("file")) {
itemView.setOnClickListener(v -> {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(individualHashMap.get("link")));
context.startActivity(browserIntent);
});
}
}
}
} else if (TextMatchers.isMessageWithSingleEmoticonOnly(message.getText())) {
textSize = (float) (textSize * 2.5);
layoutParams.setWrapBefore(true);
itemView.setSelected(true);
messageAuthor.setVisibility(View.GONE);
}
messageText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
messageTimeView.setLayoutParams(layoutParams);
messageText.setText(messageString);
}
} else if (TextMatchers.isMessageWithSingleEmoticonOnly(message.getText())) {
textSize = (float) (textSize * 2.5);
layoutParams.setWrapBefore(true);
itemView.setSelected(true);
messageAuthor.setVisibility(View.GONE);
}
messageText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
messageTimeView.setLayoutParams(layoutParams);
messageText.setText(messageString);
}
}

View File

@ -48,91 +48,99 @@ import java.util.Map;
import javax.inject.Inject;
@AutoInjector(NextcloudTalkApplication.class)
public class MagicOutcomingTextMessageViewHolder extends MessageHolders.OutcomingTextMessageViewHolder<ChatMessage> {
@BindView(R.id.messageText)
EmojiTextView messageText;
public class MagicOutcomingTextMessageViewHolder
extends MessageHolders.OutcomingTextMessageViewHolder<ChatMessage> {
@BindView(R.id.messageText)
EmojiTextView messageText;
@BindView(R.id.messageTime)
TextView messageTimeView;
@BindView(R.id.messageTime)
TextView messageTimeView;
@Inject
UserUtils userUtils;
@Inject
UserUtils userUtils;
@Inject
Context context;
@Inject
Context context;
private View itemView;
private View itemView;
public MagicOutcomingTextMessageViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
public MagicOutcomingTextMessageViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
NextcloudTalkApplication.Companion.getSharedApplication()
.getComponentApplication()
.inject(this);
this.itemView = itemView;
this.itemView = itemView;
}
@Override
public void onBind(ChatMessage message) {
super.onBind(message);
HashMap<String, HashMap<String, String>> messageParameters = message.getMessageParameters();
Spannable messageString = new SpannableString(message.getText());
itemView.setSelected(false);
messageTimeView.setTextColor(context.getResources().getColor(R.color.white60));
FlexboxLayout.LayoutParams layoutParams =
(FlexboxLayout.LayoutParams) messageTimeView.getLayoutParams();
layoutParams.setWrapBefore(false);
float textSize = context.getResources().getDimension(R.dimen.chat_text_size);
if (messageParameters != null && messageParameters.size() > 0) {
for (String key : messageParameters.keySet()) {
Map<String, String> individualHashMap = message.getMessageParameters().get(key);
if (individualHashMap != null) {
if (individualHashMap.get("type").equals("user") || individualHashMap.get("type")
.equals("guest") || individualHashMap.get("type").equals("call")) {
messageString =
DisplayUtils.searchAndReplaceWithMentionSpan(messageText.getContext(),
messageString,
individualHashMap.get("id"),
individualHashMap.get("name"),
individualHashMap.get("type"),
userUtils.getUserById(message.getActiveUser().getUserId()),
R.xml.chip_others);
} else if (individualHashMap.get("type").equals("file")) {
itemView.setOnClickListener(v -> {
Intent browserIntent =
new Intent(Intent.ACTION_VIEW, Uri.parse(individualHashMap.get("link")));
context.startActivity(browserIntent);
});
}
}
}
} else if (TextMatchers.isMessageWithSingleEmoticonOnly(message.getText())) {
textSize = (float) (textSize * 2.5);
layoutParams.setWrapBefore(true);
messageTimeView.setTextColor(context.getResources().getColor(R.color.warm_grey_four));
itemView.setSelected(true);
}
@Override
public void onBind(ChatMessage message) {
super.onBind(message);
HashMap<String, HashMap<String, String>> messageParameters = message.getMessageParameters();
Spannable messageString = new SpannableString(message.getText());
itemView.setSelected(false);
messageTimeView.setTextColor(context.getResources().getColor(R.color.white60));
FlexboxLayout.LayoutParams layoutParams = (FlexboxLayout.LayoutParams) messageTimeView.getLayoutParams();
layoutParams.setWrapBefore(false);
float textSize = context.getResources().getDimension(R.dimen.chat_text_size);
if (messageParameters != null && messageParameters.size() > 0) {
for (String key : messageParameters.keySet()) {
Map<String, String> individualHashMap = message.getMessageParameters().get(key);
if (individualHashMap != null) {
if (individualHashMap.get("type").equals("user") || individualHashMap.get("type").equals("guest") || individualHashMap.get("type").equals("call")) {
messageString =
DisplayUtils.searchAndReplaceWithMentionSpan(messageText.getContext(),
messageString,
individualHashMap.get("id"),
individualHashMap.get("name"),
individualHashMap.get("type"),
userUtils.getUserById(message.getActiveUser().getUserId()),
R.xml.chip_others);
} else if (individualHashMap.get("type").equals("file")) {
itemView.setOnClickListener(v -> {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(individualHashMap.get("link")));
context.startActivity(browserIntent);
});
}
}
}
} else if (TextMatchers.isMessageWithSingleEmoticonOnly(message.getText())) {
textSize = (float) (textSize * 2.5);
layoutParams.setWrapBefore(true);
messageTimeView.setTextColor(context.getResources().getColor(R.color.warm_grey_four));
itemView.setSelected(true);
}
Resources resources = NextcloudTalkApplication.Companion.getSharedApplication().getResources();
if (message.isGrouped) {
Drawable bubbleDrawable =
DisplayUtils.getMessageSelector(resources.getColor(R.color.bg_message_list_outcoming_bubble),
resources.getColor(R.color.transparent),
resources.getColor(R.color.bg_message_list_outcoming_bubble), R.drawable.shape_grouped_outcoming_message);
ViewCompat.setBackground(bubble, bubbleDrawable);
} else {
Drawable bubbleDrawable = DisplayUtils.getMessageSelector(resources.getColor(R.color.bg_message_list_outcoming_bubble),
resources.getColor(R.color.transparent),
resources.getColor(R.color.bg_message_list_outcoming_bubble), R.drawable.shape_outcoming_message);
ViewCompat.setBackground(bubble, bubbleDrawable);
}
messageText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
messageTimeView.setLayoutParams(layoutParams);
messageText.setText(messageString);
Resources resources = NextcloudTalkApplication.Companion.getSharedApplication().getResources();
if (message.isGrouped) {
Drawable bubbleDrawable =
DisplayUtils.getMessageSelector(
resources.getColor(R.color.bg_message_list_outcoming_bubble),
resources.getColor(R.color.transparent),
resources.getColor(R.color.bg_message_list_outcoming_bubble),
R.drawable.shape_grouped_outcoming_message);
ViewCompat.setBackground(bubble, bubbleDrawable);
} else {
Drawable bubbleDrawable = DisplayUtils.getMessageSelector(
resources.getColor(R.color.bg_message_list_outcoming_bubble),
resources.getColor(R.color.transparent),
resources.getColor(R.color.bg_message_list_outcoming_bubble),
R.drawable.shape_outcoming_message);
ViewCompat.setBackground(bubble, bubbleDrawable);
}
messageText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
messageTimeView.setLayoutParams(layoutParams);
messageText.setText(messageString);
}
}

View File

@ -55,126 +55,144 @@ import javax.inject.Inject;
import okhttp3.OkHttpClient;
@AutoInjector(NextcloudTalkApplication.class)
public class MagicPreviewMessageViewHolder extends MessageHolders.IncomingImageMessageViewHolder<ChatMessage> {
public class MagicPreviewMessageViewHolder
extends MessageHolders.IncomingImageMessageViewHolder<ChatMessage> {
@BindView(R.id.messageText)
EmojiTextView messageText;
@BindView(R.id.messageText)
EmojiTextView messageText;
@Inject
Context context;
@Inject
Context context;
@Inject
OkHttpClient okHttpClient;
@Inject
OkHttpClient okHttpClient;
public MagicPreviewMessageViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
}
public MagicPreviewMessageViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
NextcloudTalkApplication.Companion.getSharedApplication()
.getComponentApplication()
.inject(this);
}
@SuppressLint("SetTextI18n")
@Override
public void onBind(ChatMessage message) {
super.onBind(message);
if (userAvatar != null) {
if (message.isGrouped || message.isOneToOneConversation) {
if (message.isOneToOneConversation) {
userAvatar.setVisibility(View.GONE);
} else {
userAvatar.setVisibility(View.INVISIBLE);
}
} else {
userAvatar.setVisibility(View.VISIBLE);
if ("bots".equals(message.getActorType()) && "changelog".equals(message.getActorId())) {
Drawable[] layers = new Drawable[2];
layers[0] = context.getDrawable(R.drawable.ic_launcher_background);
layers[1] = context.getDrawable(R.drawable.ic_launcher_foreground);
LayerDrawable layerDrawable = new LayerDrawable(layers);
userAvatar.getHierarchy().setPlaceholderImage(DisplayUtils.getRoundedDrawable(layerDrawable));
}
}
}
if (message.getMessageType() == ChatMessage.MessageType.SINGLE_NC_ATTACHMENT_MESSAGE) {
// it's a preview for a Nextcloud share
messageText.setText(message.getSelectedIndividualHashMap().get("name"));
DisplayUtils.setClickableString(message.getSelectedIndividualHashMap().get("name"), message.getSelectedIndividualHashMap().get("link"), messageText);
if (message.getSelectedIndividualHashMap().containsKey("mimetype")) {
image.getHierarchy().setPlaceholderImage(context.getDrawable(DrawableUtils.INSTANCE.getDrawableResourceIdForMimeType(message.getSelectedIndividualHashMap().get("mimetype"))));
} else {
fetchFileInformation("/" + message.getSelectedIndividualHashMap().get("path"), message.getActiveUser());
}
image.setOnClickListener(v -> {
String accountString =
message.getActiveUser().getUsername() + "@" + message.getActiveUser().getBaseUrl().replace("https://", "").replace("http://", "");
if (AccountUtils.INSTANCE.canWeOpenFilesApp(context, accountString)) {
Intent filesAppIntent = new Intent(Intent.ACTION_VIEW, null);
final ComponentName componentName = new ComponentName(context.getString(R.string.nc_import_accounts_from), "com.owncloud.android.ui.activity.FileDisplayActivity");
filesAppIntent.setComponent(componentName);
filesAppIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
filesAppIntent.setPackage(context.getString(R.string.nc_import_accounts_from));
filesAppIntent.putExtra(BundleKeys.INSTANCE.getKEY_ACCOUNT(), accountString);
filesAppIntent.putExtra(BundleKeys.INSTANCE.getKEY_FILE_ID(), message.getSelectedIndividualHashMap().get("id"));
context.startActivity(filesAppIntent);
} else {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(message.getSelectedIndividualHashMap().get("link")));
browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(browserIntent);
}
});
} else if (message.getMessageType() == ChatMessage.MessageType.SINGLE_LINK_GIPHY_MESSAGE) {
messageText.setText("GIPHY");
DisplayUtils.setClickableString("GIPHY", "https://giphy.com", messageText);
} else if (message.getMessageType() == ChatMessage.MessageType.SINGLE_LINK_TENOR_MESSAGE) {
messageText.setText("Tenor");
DisplayUtils.setClickableString("Tenor", "https://tenor.com", messageText);
@SuppressLint("SetTextI18n")
@Override
public void onBind(ChatMessage message) {
super.onBind(message);
if (userAvatar != null) {
if (message.isGrouped || message.isOneToOneConversation) {
if (message.isOneToOneConversation) {
userAvatar.setVisibility(View.GONE);
} else {
if (message.getMessageType().equals(ChatMessage.MessageType.SINGLE_LINK_IMAGE_MESSAGE)) {
image.setOnClickListener(v -> {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(message.getImageUrl()));
browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(browserIntent);
});
} else {
image.setOnClickListener(null);
}
messageText.setText("");
userAvatar.setVisibility(View.INVISIBLE);
}
} else {
userAvatar.setVisibility(View.VISIBLE);
if ("bots".equals(message.getActorType()) && "changelog".equals(message.getActorId())) {
Drawable[] layers = new Drawable[2];
layers[0] = context.getDrawable(R.drawable.ic_launcher_background);
layers[1] = context.getDrawable(R.drawable.ic_launcher_foreground);
LayerDrawable layerDrawable = new LayerDrawable(layers);
userAvatar.getHierarchy()
.setPlaceholderImage(DisplayUtils.getRoundedDrawable(layerDrawable));
}
}
}
private void fetchFileInformation(String url, UserEntity activeUser) {
Single.fromCallable(new Callable<ReadFilesystemOperation>() {
@Override
public ReadFilesystemOperation call() {
return new ReadFilesystemOperation(okHttpClient, activeUser, url, 0);
if (message.getMessageType() == ChatMessage.MessageType.SINGLE_NC_ATTACHMENT_MESSAGE) {
// it's a preview for a Nextcloud share
messageText.setText(message.getSelectedIndividualHashMap().get("name"));
DisplayUtils.setClickableString(message.getSelectedIndividualHashMap().get("name"),
message.getSelectedIndividualHashMap().get("link"), messageText);
if (message.getSelectedIndividualHashMap().containsKey("mimetype")) {
image.getHierarchy()
.setPlaceholderImage(context.getDrawable(
DrawableUtils.INSTANCE.getDrawableResourceIdForMimeType(
message.getSelectedIndividualHashMap().get("mimetype"))));
} else {
fetchFileInformation("/" + message.getSelectedIndividualHashMap().get("path"),
message.getActiveUser());
}
image.setOnClickListener(v -> {
String accountString =
message.getActiveUser().getUsername() + "@" + message.getActiveUser()
.getBaseUrl()
.replace("https://", "")
.replace("http://", "");
if (AccountUtils.INSTANCE.canWeOpenFilesApp(context, accountString)) {
Intent filesAppIntent = new Intent(Intent.ACTION_VIEW, null);
final ComponentName componentName =
new ComponentName(context.getString(R.string.nc_import_accounts_from),
"com.owncloud.android.ui.activity.FileDisplayActivity");
filesAppIntent.setComponent(componentName);
filesAppIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
filesAppIntent.setPackage(context.getString(R.string.nc_import_accounts_from));
filesAppIntent.putExtra(BundleKeys.INSTANCE.getKEY_ACCOUNT(), accountString);
filesAppIntent.putExtra(BundleKeys.INSTANCE.getKEY_FILE_ID(),
message.getSelectedIndividualHashMap().get("id"));
context.startActivity(filesAppIntent);
} else {
Intent browserIntent = new Intent(Intent.ACTION_VIEW,
Uri.parse(message.getSelectedIndividualHashMap().get("link")));
browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(browserIntent);
}
});
} else if (message.getMessageType() == ChatMessage.MessageType.SINGLE_LINK_GIPHY_MESSAGE) {
messageText.setText("GIPHY");
DisplayUtils.setClickableString("GIPHY", "https://giphy.com", messageText);
} else if (message.getMessageType() == ChatMessage.MessageType.SINGLE_LINK_TENOR_MESSAGE) {
messageText.setText("Tenor");
DisplayUtils.setClickableString("Tenor", "https://tenor.com", messageText);
} else {
if (message.getMessageType().equals(ChatMessage.MessageType.SINGLE_LINK_IMAGE_MESSAGE)) {
image.setOnClickListener(v -> {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(message.getImageUrl()));
browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(browserIntent);
});
} else {
image.setOnClickListener(null);
}
messageText.setText("");
}
}
private void fetchFileInformation(String url, UserEntity activeUser) {
Single.fromCallable(new Callable<ReadFilesystemOperation>() {
@Override
public ReadFilesystemOperation call() {
return new ReadFilesystemOperation(okHttpClient, activeUser, url, 0);
}
}).observeOn(Schedulers.io())
.subscribe(new SingleObserver<ReadFilesystemOperation>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onSuccess(ReadFilesystemOperation readFilesystemOperation) {
DavResponse davResponse = readFilesystemOperation.readRemotePath();
if (davResponse.getData() != null) {
List<BrowserFile> browserFileList = (List<BrowserFile>) davResponse.getData();
if (!browserFileList.isEmpty()) {
new Handler(context.getMainLooper()).post(() -> image.getHierarchy()
.setPlaceholderImage(context.getDrawable(
DrawableUtils.INSTANCE.getDrawableResourceIdForMimeType(
browserFileList.get(0).getMimeType()))));
}
}
}).observeOn(Schedulers.io())
.subscribe(new SingleObserver<ReadFilesystemOperation>() {
@Override
public void onSubscribe(Disposable d) {
}
}
@Override
public void onSuccess(ReadFilesystemOperation readFilesystemOperation) {
DavResponse davResponse = readFilesystemOperation.readRemotePath();
if (davResponse.getData() != null) {
List<BrowserFile> browserFileList = (List<BrowserFile>) davResponse.getData();
if (!browserFileList.isEmpty()) {
new Handler(context.getMainLooper()).post(() -> image.getHierarchy().setPlaceholderImage(context.getDrawable(DrawableUtils.INSTANCE.getDrawableResourceIdForMimeType(browserFileList.get(0).getMimeType()))));
}
}
}
@Override
public void onError(Throwable e) {
}
});
}
@Override
public void onError(Throwable e) {
}
});
}
}

View File

@ -38,48 +38,54 @@ import java.util.Map;
import javax.inject.Inject;
@AutoInjector(NextcloudTalkApplication.class)
public class MagicSystemMessageViewHolder extends MessageHolders.IncomingTextMessageViewHolder<ChatMessage> {
public class MagicSystemMessageViewHolder
extends MessageHolders.IncomingTextMessageViewHolder<ChatMessage> {
@Inject
AppPreferences appPreferences;
@Inject
AppPreferences appPreferences;
@Inject
Context context;
@Inject
Context context;
public MagicSystemMessageViewHolder(View itemView) {
super(itemView);
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
}
public MagicSystemMessageViewHolder(View itemView) {
super(itemView);
NextcloudTalkApplication.Companion.getSharedApplication()
.getComponentApplication()
.inject(this);
}
@Override
public void onBind(ChatMessage message) {
super.onBind(message);
@Override
public void onBind(ChatMessage message) {
super.onBind(message);
Resources resources = itemView.getResources();
int normalColor = resources.getColor(R.color.bg_message_list_incoming_bubble);
int pressedColor;
int mentionColor;
Resources resources = itemView.getResources();
int normalColor = resources.getColor(R.color.bg_message_list_incoming_bubble);
int pressedColor;
int mentionColor;
pressedColor = normalColor;
mentionColor = resources.getColor(R.color.nc_author_text);
pressedColor = normalColor;
mentionColor = resources.getColor(R.color.nc_author_text);
Drawable bubbleDrawable = DisplayUtils.getMessageSelector(normalColor,
resources.getColor(R.color.transparent), pressedColor,
R.drawable.shape_grouped_incoming_message);
ViewCompat.setBackground(bubble, bubbleDrawable);
Drawable bubbleDrawable = DisplayUtils.getMessageSelector(normalColor,
resources.getColor(R.color.transparent), pressedColor,
R.drawable.shape_grouped_incoming_message);
ViewCompat.setBackground(bubble, bubbleDrawable);
Spannable messageString = new SpannableString(message.getText());
Spannable messageString = new SpannableString(message.getText());
if (message.getMessageParameters() != null && message.getMessageParameters().size() > 0) {
for (String key : message.getMessageParameters().keySet()) {
Map<String, String> individualHashMap = message.getMessageParameters().get(key);
if (individualHashMap != null && (individualHashMap.get("type").equals("user") || individualHashMap.get("type").equals("guest") || individualHashMap.get("type").equals("call"))) {
messageString = DisplayUtils.searchAndColor(messageString, "@" + individualHashMap.get("name"), mentionColor);
}
}
if (message.getMessageParameters() != null && message.getMessageParameters().size() > 0) {
for (String key : message.getMessageParameters().keySet()) {
Map<String, String> individualHashMap = message.getMessageParameters().get(key);
if (individualHashMap != null && (individualHashMap.get("type").equals("user")
|| individualHashMap.get("type").equals("guest")
|| individualHashMap.get("type").equals("call"))) {
messageString =
DisplayUtils.searchAndColor(messageString, "@" + individualHashMap.get("name"),
mentionColor);
}
text.setText(messageString);
}
}
text.setText(messageString);
}
}

View File

@ -24,27 +24,28 @@ import android.view.View;
import com.nextcloud.talk.models.json.chat.ChatMessage;
import com.stfalcon.chatkit.messages.MessageHolders;
public class MagicUnreadNoticeMessageViewHolder extends MessageHolders.SystemMessageViewHolder<ChatMessage> {
public class MagicUnreadNoticeMessageViewHolder
extends MessageHolders.SystemMessageViewHolder<ChatMessage> {
public MagicUnreadNoticeMessageViewHolder(View itemView) {
super(itemView);
}
public MagicUnreadNoticeMessageViewHolder(View itemView) {
super(itemView);
}
public MagicUnreadNoticeMessageViewHolder(View itemView, Object payload) {
super(itemView, payload);
}
public MagicUnreadNoticeMessageViewHolder(View itemView, Object payload) {
super(itemView, payload);
}
@Override
public void viewDetached() {
messagesListAdapter.deleteById("-1");
}
@Override
public void viewDetached() {
messagesListAdapter.deleteById("-1");
}
@Override
public void viewAttached() {
}
@Override
public void viewAttached() {
}
@Override
public void viewRecycled() {
@Override
public void viewRecycled() {
}
}
}

View File

@ -54,36 +54,37 @@ import retrofit2.http.Url;
public interface NcApi {
/*
QueryMap items are as follows:
- "format" : "json"
- "search" : ""
- "perPage" : "200"
- "itemType" : "call"
/*
QueryMap items are as follows:
- "format" : "json"
- "search" : ""
- "perPage" : "200"
- "itemType" : "call"
Server URL is: baseUrl + ocsApiVersion + /apps/files_sharing/api/v1/sharees
Server URL is: baseUrl + ocsApiVersion + /apps/files_sharing/api/v1/sharees
or if we're on 14 and up:
or if we're on 14 and up:
baseUrl + ocsApiVersion + "/core/autocomplete/get");
baseUrl + ocsApiVersion + "/core/autocomplete/get");
*/
@GET
Observable<ResponseBody> getContactsWithSearchParam(@Header("Authorization") String authorization, @Url String url,
@Nullable @Query("shareTypes[]") List<String> listOfShareTypes, @QueryMap Map<String, Object> options);
*/
@GET
Observable<ResponseBody> getContactsWithSearchParam(@Header("Authorization") String authorization,
@Url String url,
@Nullable @Query("shareTypes[]") List<String> listOfShareTypes,
@QueryMap Map<String, Object> options);
/*
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /room
*/
@GET
Observable<RoomsOverall> getRooms(@Header("Authorization") String authorization, @Url String url);
/*
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /room
*/
@GET
Observable<RoomsOverall> getRooms(@Header("Authorization") String authorization, @Url String url);
/*
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /room/roomToken
*/
@GET
Observable<RoomOverall> getRoom(@Header("Authorization") String authorization, @Url String url);
/*
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /room/roomToken
*/
@GET
Observable<RoomOverall> getRoom(@Header("Authorization") String authorization, @Url String url);
/*
QueryMap items are as follows:
@ -93,9 +94,9 @@ public interface NcApi {
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /room
*/
@POST
Observable<RoomOverall> createRoom(@Header("Authorization") String authorization, @Url String url,
@QueryMap Map<String, String> options);
@POST
Observable<RoomOverall> createRoom(@Header("Authorization") String authorization, @Url String url,
@QueryMap Map<String, String> options);
/*
QueryMap items are as follows:
@ -104,109 +105,126 @@ public interface NcApi {
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /room/roomToken
*/
@FormUrlEncoded
@PUT
Observable<GenericOverall> renameRoom(@Header("Authorization") String authorization, @Url String url,
@Field("roomName") String roomName);
@FormUrlEncoded
@PUT
Observable<GenericOverall> renameRoom(@Header("Authorization") String authorization,
@Url String url,
@Field("roomName") String roomName);
/*
QueryMap items are as follows:
- "newParticipant" : "user"
/*
QueryMap items are as follows:
- "newParticipant" : "user"
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /room/roomToken/participants
*/
@POST
Observable<AddParticipantOverall> addParticipant(@Header("Authorization") String authorization,
@Url String url,
@QueryMap Map<String, String> options);
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /room/roomToken/participants
*/
@POST
Observable<AddParticipantOverall> addParticipant(@Header("Authorization") String authorization, @Url String url,
@QueryMap Map<String, String> options);
// also used for removing a guest from a conversation
@DELETE
Observable<GenericOverall> removeParticipantFromConversation(
@Header("Authorization") String authorization, @Url String url,
@Query("participant") String participantId);
@POST
Observable<GenericOverall> promoteUserToModerator(@Header("Authorization") String authorization,
@Url String url, @Query("participant") String participantId);
// also used for removing a guest from a conversation
@DELETE
Observable<GenericOverall> removeParticipantFromConversation(@Header("Authorization") String authorization, @Url String url, @Query("participant") String participantId);
@POST
Observable<GenericOverall> promoteUserToModerator(@Header("Authorization") String authorization, @Url String url, @Query("participant") String participantId);
@DELETE
Observable<GenericOverall> demoteModeratorToUser(@Header("Authorization") String authorization, @Url String url, @Query("participant") String participantId);
@DELETE
Observable<GenericOverall> demoteModeratorToUser(@Header("Authorization") String authorization,
@Url String url, @Query("participant") String participantId);
/*
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /room/roomToken/participants/self
*/
@DELETE
Observable<GenericOverall> removeSelfFromRoom(@Header("Authorization") String authorization, @Url String url);
@DELETE
Observable<GenericOverall> removeSelfFromRoom(@Header("Authorization") String authorization,
@Url String url);
/*
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /room/roomToken/public
*/
@POST
Observable<GenericOverall> makeRoomPublic(@Header("Authorization") String authorization, @Url String url);
/*
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /room/roomToken/public
*/
@POST
Observable<GenericOverall> makeRoomPublic(@Header("Authorization") String authorization,
@Url String url);
/*
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /room/roomToken/public
*/
@DELETE
Observable<GenericOverall> makeRoomPrivate(@Header("Authorization") String authorization, @Url String url);
/*
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /room/roomToken/public
*/
@DELETE
Observable<GenericOverall> makeRoomPrivate(@Header("Authorization") String authorization,
@Url String url);
@DELETE
Observable<GenericOverall> deleteRoom(@Header("Authorization") String authorization, @Url String url);
@DELETE
Observable<GenericOverall> deleteRoom(@Header("Authorization") String authorization,
@Url String url);
/*
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /call/callToken
*/
@GET
Observable<ParticipantsOverall> getPeersForCall(@Header("Authorization") String authorization, @Url String url);
/*
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /call/callToken
*/
@GET
Observable<ParticipantsOverall> getPeersForCall(@Header("Authorization") String authorization,
@Url String url);
@FormUrlEncoded
@POST
Observable<RoomOverall> joinRoom(@Nullable @Header("Authorization") String authorization, @Url String url, @Nullable @Field("password") String password);
@FormUrlEncoded
@POST
Observable<RoomOverall> joinRoom(@Nullable @Header("Authorization") String authorization,
@Url String url, @Nullable @Field("password") String password);
@DELETE
Observable<GenericOverall> leaveRoom(@Nullable @Header("Authorization") String authorization, @Url String url);
@DELETE
Observable<GenericOverall> leaveRoom(@Nullable @Header("Authorization") String authorization,
@Url String url);
/*
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /call/callToken
*/
@POST
Observable<GenericOverall> joinCall(@Nullable @Header("Authorization") String authorization, @Url String url);
@POST
Observable<GenericOverall> joinCall(@Nullable @Header("Authorization") String authorization,
@Url String url);
/*
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /call/callToken
*/
@DELETE
Observable<GenericOverall> leaveCall(@Nullable @Header("Authorization") String authorization, @Url String url);
/*
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /call/callToken
*/
@DELETE
Observable<GenericOverall> leaveCall(@Nullable @Header("Authorization") String authorization,
@Url String url);
/*
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /call/callToken/ping
*/
@POST
Observable<GenericOverall> pingCall(@Nullable @Header("Authorization") String authorization, @Url String url);
/*
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /call/callToken/ping
*/
@POST
Observable<GenericOverall> pingCall(@Nullable @Header("Authorization") String authorization,
@Url String url);
@GET
Observable<SignalingSettingsOverall> getSignalingSettings(@Nullable @Header("Authorization") String authorization,
@Url String url);
@GET
Observable<SignalingSettingsOverall> getSignalingSettings(
@Nullable @Header("Authorization") String authorization,
@Url String url);
/*
QueryMap items are as follows:
- "messages" : "message"
/*
QueryMap items are as follows:
- "messages" : "message"
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /signaling
*/
@FormUrlEncoded
@POST
Observable<SignalingOverall> sendSignalingMessages(@Nullable @Header("Authorization") String authorization, @Url String url,
@Field("messages") String messages);
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /signaling
*/
@FormUrlEncoded
@POST
Observable<SignalingOverall> sendSignalingMessages(
@Nullable @Header("Authorization") String authorization, @Url String url,
@Field("messages") String messages);
/*
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /signaling
*/
@GET
Observable<SignalingOverall> pullSignalingMessages(@Nullable @Header("Authorization") String authorization, @Url
String
url);
/*
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /signaling
*/
@GET
Observable<SignalingOverall> pullSignalingMessages(
@Nullable @Header("Authorization") String authorization, @Url
String
url);
/*
QueryMap items are as follows:
@ -215,14 +233,15 @@ public interface NcApi {
Server URL is: baseUrl + ocsApiVersion + "/cloud/user"
*/
@GET
Observable<UserProfileOverall> getUserProfile(@Header("Authorization") String authorization, @Url String url);
@GET
Observable<UserProfileOverall> getUserProfile(@Header("Authorization") String authorization,
@Url String url);
/*
Server URL is: baseUrl + /status.php
*/
@GET
Observable<Status> getServerStatus(@Url String url);
/*
Server URL is: baseUrl + /status.php
*/
@GET
Observable<Status> getServerStatus(@Url String url);
/*
@ -235,52 +254,55 @@ public interface NcApi {
Server URL is: baseUrl + ocsApiVersion + "/apps/notifications/api/v2/push
*/
@POST
Observable<PushRegistrationOverall> registerDeviceForNotificationsWithNextcloud(@Header("Authorization")
String authorization,
@Url String url,
@QueryMap Map<String,
String> options);
@POST
Observable<PushRegistrationOverall> registerDeviceForNotificationsWithNextcloud(
@Header("Authorization")
String authorization,
@Url String url,
@QueryMap Map<String,
String> options);
@DELETE
Observable<GenericOverall> unregisterDeviceForNotificationsWithNextcloud(@Header("Authorization")
String authorization,
@Url String url);
@DELETE
Observable<GenericOverall> unregisterDeviceForNotificationsWithNextcloud(@Header("Authorization")
String authorization,
@Url String url);
@FormUrlEncoded
@POST
Observable<Void> registerDeviceForNotificationsWithProxy(@Url String url,
@FieldMap Map<String, String> fields);
@FormUrlEncoded
@POST
Observable<Void> registerDeviceForNotificationsWithProxy(@Url String url,
@FieldMap Map<String, String> fields);
/*
QueryMap items are as follows:
- "deviceIdentifier": "{{deviceIdentifier}}",
- "deviceIdentifierSignature": "{{signature}}",
- "userPublicKey": "{{userPublicKey}}"
*/
@DELETE
Observable<Void> unregisterDeviceForNotificationsWithProxy(@Url String url,
@QueryMap Map<String, String> fields);
/*
QueryMap items are as follows:
- "deviceIdentifier": "{{deviceIdentifier}}",
- "deviceIdentifierSignature": "{{signature}}",
- "userPublicKey": "{{userPublicKey}}"
*/
@DELETE
Observable<Void> unregisterDeviceForNotificationsWithProxy(@Url String url,
@QueryMap Map<String, String> fields);
@FormUrlEncoded
@PUT
Observable<GenericOverall> setPassword(@Header("Authorization") String authorization,
@Url String url,
@Field("password") String password);
@FormUrlEncoded
@PUT
Observable<GenericOverall> setPassword(@Header("Authorization") String authorization, @Url String url,
@Field("password") String password);
@GET
Observable<CapabilitiesOverall> getCapabilities(@Header("Authorization") String authorization,
@Url String url);
@GET
Observable<CapabilitiesOverall> getCapabilities(@Header("Authorization") String authorization, @Url String url);
/*
QueryMap items are as follows:
- "lookIntoFuture": int (0 or 1),
- "limit" : int, range 100-200,
- "timeout": used with look into future, 30 default, 60 at most
- "lastKnownMessageId", int, use one from X-Chat-Last-Given
*/
@GET
Observable<Response<ChatOverall>> pullChatMessages(@Header("Authorization") String authorization, @Url String url,
@QueryMap Map<String, Integer> fields);
/*
QueryMap items are as follows:
- "lookIntoFuture": int (0 or 1),
- "limit" : int, range 100-200,
- "timeout": used with look into future, 30 default, 60 at most
- "lastKnownMessageId", int, use one from X-Chat-Last-Given
*/
@GET
Observable<Response<ChatOverall>> pullChatMessages(@Header("Authorization") String authorization,
@Url String url,
@QueryMap Map<String, Integer> fields);
/*
Fieldmap items are as follows:
@ -288,51 +310,56 @@ public interface NcApi {
- "actorDisplayName"
*/
@FormUrlEncoded
@POST
Observable<GenericOverall> sendChatMessage(@Header("Authorization") String authorization, @Url String url,
@Field("message") CharSequence message,
@Field("actorDisplayName") String actorDisplayName);
@FormUrlEncoded
@POST
Observable<GenericOverall> sendChatMessage(@Header("Authorization") String authorization,
@Url String url,
@Field("message") CharSequence message,
@Field("actorDisplayName") String actorDisplayName);
@GET
Observable<MentionOverall> getMentionAutocompleteSuggestions(@Header("Authorization") String authorization,
@Url String url, @Query("search") String query,
@Nullable @Query("limit") Integer limit);
@GET
Observable<MentionOverall> getMentionAutocompleteSuggestions(
@Header("Authorization") String authorization,
@Url String url, @Query("search") String query,
@Nullable @Query("limit") Integer limit);
// Url is: /api/{apiVersion}/room/{token}/pin
@POST
Observable<GenericOverall> addConversationToFavorites(@Header("Authorization") String authorization,
@Url String url);
// Url is: /api/{apiVersion}/room/{token}/pin
@POST
Observable<GenericOverall> addConversationToFavorites(
@Header("Authorization") String authorization,
@Url String url);
// Url is: /api/{apiVersion}/room/{token}/favorites
@DELETE
Observable<GenericOverall> removeConversationFromFavorites(@Header("Authorization") String authorization,
@Url String url);
// Url is: /api/{apiVersion}/room/{token}/favorites
@DELETE
Observable<GenericOverall> removeConversationFromFavorites(
@Header("Authorization") String authorization,
@Url String url);
@GET
Observable<NotificationOverall> getNotification(@Header("Authorization") String authorization,
@Url String url);
@GET
Observable<NotificationOverall> getNotification(@Header("Authorization") String authorization,
@Url String url);
@FormUrlEncoded
@POST
Observable<GenericOverall> setNotificationLevel(@Header("Authorization") String authorization, @Url String url, @Field("level") int level);
@FormUrlEncoded
@POST
Observable<GenericOverall> setNotificationLevel(@Header("Authorization") String authorization,
@Url String url, @Field("level") int level);
@FormUrlEncoded
@PUT
Observable<GenericOverall> setReadOnlyState(@Header("Authorization") String authorization, @Url String url, @Field("viewState") int state);
@FormUrlEncoded
@PUT
Observable<GenericOverall> setReadOnlyState(@Header("Authorization") String authorization,
@Url String url, @Field("viewState") int state);
@FormUrlEncoded
@POST
Observable<Void> createRemoteShare(@Nullable @Header("Authorization") String authorization,
@Url String url,
@Field("path") String remotePath,
@Field("shareWith") String roomToken,
@Field("shareType") String shareType);
@FormUrlEncoded
@POST
Observable<Void> createRemoteShare(@Nullable @Header("Authorization") String authorization, @Url String url,
@Field("path") String remotePath,
@Field("shareWith") String roomToken,
@Field("shareType") String shareType);
@FormUrlEncoded
@PUT
Observable<GenericOverall> setLobbyForConversation(@Header("Authorization") String authorization,
@Url String url, @Field("viewState") Integer state,
@Field("timer") Long timer);
@FormUrlEncoded
@PUT
Observable<GenericOverall> setLobbyForConversation(@Header("Authorization") String authorization,
@Url String url, @Field("viewState") Integer state,
@Field("timer") Long timer);
}

View File

@ -29,7 +29,6 @@ import androidx.emoji.bundled.BundledEmojiCompatConfig
import androidx.emoji.text.EmojiCompat
import androidx.lifecycle.LifecycleObserver
import androidx.multidex.MultiDex
import androidx.multidex.MultiDexApplication
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.OneTimeWorkRequest
import androidx.work.PeriodicWorkRequest
@ -54,7 +53,6 @@ import com.nextcloud.talk.newarch.di.module.NetworkModule
import com.nextcloud.talk.newarch.di.module.StorageModule
import com.nextcloud.talk.newarch.features.conversationsList.di.module.ConversationsListModule
import com.nextcloud.talk.utils.ClosedInterfaceImpl
import com.nextcloud.talk.utils.DeviceUtils
import com.nextcloud.talk.utils.DisplayUtils
import com.nextcloud.talk.utils.OkHttpNetworkFetcherWithCache
import com.nextcloud.talk.utils.database.arbitrarystorage.ArbitraryStorageModule
@ -78,150 +76,174 @@ import java.util.concurrent.TimeUnit
import javax.inject.Inject
import javax.inject.Singleton
@AutoComponent(modules = [BusModule::class, ContextModule::class, DatabaseModule::class, RestModule::class, UserModule::class, ArbitraryStorageModule::class])
@AutoComponent(
modules = [BusModule::class, ContextModule::class, DatabaseModule::class, RestModule::class, UserModule::class, ArbitraryStorageModule::class]
)
@Singleton
@AutoInjector(NextcloudTalkApplication::class)
class NextcloudTalkApplication : Application(), LifecycleObserver {
//region Fields (components)
lateinit var componentApplication: NextcloudTalkApplicationComponent
private set
//endregion
//region Fields (components)
lateinit var componentApplication: NextcloudTalkApplicationComponent
private set
//endregion
//region Getters
//region Getters
@Inject
lateinit var appPreferences: AppPreferences
@Inject
lateinit var okHttpClient: OkHttpClient
//endregion
@Inject
lateinit var appPreferences: AppPreferences
@Inject
lateinit var okHttpClient: OkHttpClient
//endregion
//region private methods
private fun initializeWebRtc() {
try {
if (MagicWebRTCUtils.HARDWARE_AEC_BLACKLIST.contains(Build.MODEL)) {
WebRtcAudioUtils.setWebRtcBasedAcousticEchoCanceler(true)
}
//region private methods
private fun initializeWebRtc() {
try {
if (MagicWebRTCUtils.HARDWARE_AEC_BLACKLIST.contains(Build.MODEL)) {
WebRtcAudioUtils.setWebRtcBasedAcousticEchoCanceler(true)
}
if (!MagicWebRTCUtils.OPEN_SL_ES_WHITELIST.contains(Build.MODEL)) {
WebRtcAudioManager.setBlacklistDeviceForOpenSLESUsage(true)
}
if (!MagicWebRTCUtils.OPEN_SL_ES_WHITELIST.contains(Build.MODEL)) {
WebRtcAudioManager.setBlacklistDeviceForOpenSLESUsage(true)
}
PeerConnectionFactory.initialize(PeerConnectionFactory.InitializationOptions.builder(this)
.setEnableVideoHwAcceleration(MagicWebRTCUtils.shouldEnableVideoHardwareAcceleration())
.createInitializationOptions())
} catch (e: UnsatisfiedLinkError) {
Log.w(TAG, e)
}
PeerConnectionFactory.initialize(
PeerConnectionFactory.InitializationOptions.builder(this)
.setEnableVideoHwAcceleration(
MagicWebRTCUtils.shouldEnableVideoHardwareAcceleration()
)
.createInitializationOptions()
)
} catch (e: UnsatisfiedLinkError) {
Log.w(TAG, e)
}
//endregion
}
//region Overridden methods
override fun onCreate() {
sharedApplication = this
//endregion
val securityKeyManager = SecurityKeyManager.getInstance()
val securityKeyConfig = SecurityKeyManagerConfig.Builder()
.setEnableDebugLogging(BuildConfig.DEBUG)
//region Overridden methods
override fun onCreate() {
sharedApplication = this
val securityKeyManager = SecurityKeyManager.getInstance()
val securityKeyConfig = SecurityKeyManagerConfig.Builder()
.setEnableDebugLogging(BuildConfig.DEBUG)
.build()
securityKeyManager.init(this, securityKeyConfig)
initializeWebRtc()
DisplayUtils.useCompatVectorIfNeeded()
buildComponent()
DavUtils.registerCustomFactories()
componentApplication.inject(this)
setAppTheme(appPreferences.theme)
super.onCreate()
val imagePipelineConfig = ImagePipelineConfig.newBuilder(this)
.setNetworkFetcher(OkHttpNetworkFetcherWithCache(okHttpClient))
.setMainDiskCacheConfig(
DiskCacheConfig.newBuilder(this)
.setMaxCacheSize(0)
.setMaxCacheSizeOnLowDiskSpace(0)
.setMaxCacheSizeOnVeryLowDiskSpace(0)
.build()
securityKeyManager.init(this, securityKeyConfig)
)
.build()
initializeWebRtc()
DisplayUtils.useCompatVectorIfNeeded()
buildComponent()
DavUtils.registerCustomFactories()
Fresco.initialize(this, imagePipelineConfig)
Security.insertProviderAt(Conscrypt.newProvider(), 1)
componentApplication.inject(this)
ClosedInterfaceImpl().providerInstallerInstallIfNeededAsync()
setAppTheme(appPreferences.theme)
super.onCreate()
val pushRegistrationWork = OneTimeWorkRequest.Builder(PushRegistrationWorker::class.java)
.build()
val accountRemovalWork = OneTimeWorkRequest.Builder(AccountRemovalWorker::class.java)
.build()
val periodicCapabilitiesUpdateWork = PeriodicWorkRequest.Builder(
CapabilitiesWorker::class.java,
12, TimeUnit.HOURS
)
.build()
val capabilitiesUpdateWork = OneTimeWorkRequest.Builder(CapabilitiesWorker::class.java)
.build()
val signalingSettingsWork = OneTimeWorkRequest.Builder(SignalingSettingsWorker::class.java)
.build()
val imagePipelineConfig = ImagePipelineConfig.newBuilder(this)
.setNetworkFetcher(OkHttpNetworkFetcherWithCache(okHttpClient))
.setMainDiskCacheConfig(DiskCacheConfig.newBuilder(this)
.setMaxCacheSize(0)
.setMaxCacheSizeOnLowDiskSpace(0)
.setMaxCacheSizeOnVeryLowDiskSpace(0)
.build())
.build()
WorkManager.getInstance()
.enqueue(pushRegistrationWork)
WorkManager.getInstance()
.enqueue(accountRemovalWork)
WorkManager.getInstance()
.enqueue(capabilitiesUpdateWork)
WorkManager.getInstance()
.enqueue(signalingSettingsWork)
WorkManager.getInstance()
.enqueueUniquePeriodicWork(
"DailyCapabilitiesUpdateWork", ExistingPeriodicWorkPolicy.REPLACE,
periodicCapabilitiesUpdateWork
)
Fresco.initialize(this, imagePipelineConfig)
Security.insertProviderAt(Conscrypt.newProvider(), 1)
val config = BundledEmojiCompatConfig(this)
config.setReplaceAll(true)
val emojiCompat = EmojiCompat.init(config)
ClosedInterfaceImpl().providerInstallerInstallIfNeededAsync()
EmojiManager.install(GoogleCompatEmojiProvider(emojiCompat))
}
val pushRegistrationWork = OneTimeWorkRequest.Builder(PushRegistrationWorker::class.java).build()
val accountRemovalWork = OneTimeWorkRequest.Builder(AccountRemovalWorker::class.java).build()
val periodicCapabilitiesUpdateWork = PeriodicWorkRequest.Builder(CapabilitiesWorker::class.java,
12, TimeUnit.HOURS).build()
val capabilitiesUpdateWork = OneTimeWorkRequest.Builder(CapabilitiesWorker::class.java).build()
val signalingSettingsWork = OneTimeWorkRequest.Builder(SignalingSettingsWorker::class.java).build()
override fun onTerminate() {
super.onTerminate()
sharedApplication = null
}
//endregion
WorkManager.getInstance().enqueue(pushRegistrationWork)
WorkManager.getInstance().enqueue(accountRemovalWork)
WorkManager.getInstance().enqueue(capabilitiesUpdateWork)
WorkManager.getInstance().enqueue(signalingSettingsWork)
WorkManager.getInstance().enqueueUniquePeriodicWork("DailyCapabilitiesUpdateWork", ExistingPeriodicWorkPolicy.REPLACE, periodicCapabilitiesUpdateWork)
//region Protected methods
protected fun buildComponent() {
componentApplication = DaggerNextcloudTalkApplicationComponent.builder()
.busModule(BusModule())
.contextModule(ContextModule(applicationContext))
.databaseModule(DatabaseModule())
.restModule(RestModule(applicationContext))
.userModule(UserModule())
.arbitraryStorageModule(ArbitraryStorageModule())
.build()
val config = BundledEmojiCompatConfig(this)
config.setReplaceAll(true)
val emojiCompat = EmojiCompat.init(config)
EmojiManager.install(GoogleCompatEmojiProvider(emojiCompat))
startKoin {
androidContext(this@NextcloudTalkApplication)
androidLogger()
modules(listOf(CommunicationModule, StorageModule, NetworkModule, ConversationsListModule))
}
}
override fun onTerminate() {
super.onTerminate()
sharedApplication = null
}
override fun attachBaseContext(base: Context) {
super.attachBaseContext(base)
MultiDex.install(this)
}
companion object {
private val TAG = NextcloudTalkApplication::class.java.simpleName
//region Singleton
//endregion
//region Protected methods
protected fun buildComponent() {
componentApplication = DaggerNextcloudTalkApplicationComponent.builder()
.busModule(BusModule())
.contextModule(ContextModule(applicationContext))
.databaseModule(DatabaseModule())
.restModule(RestModule(applicationContext))
.userModule(UserModule())
.arbitraryStorageModule(ArbitraryStorageModule())
.build()
startKoin {
androidContext(this@NextcloudTalkApplication)
androidLogger()
modules(listOf(CommunicationModule, StorageModule, NetworkModule, ConversationsListModule))
}
}
override fun attachBaseContext(base: Context) {
super.attachBaseContext(base)
MultiDex.install(this)
}
companion object {
private val TAG = NextcloudTalkApplication::class.java.simpleName
//region Singleton
//endregion
var sharedApplication: NextcloudTalkApplication? = null
protected set
//endregion
//region Setters
fun setAppTheme(theme: String) {
when (theme) {
"night_no" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
"night_yes" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
"battery_saver" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY)
else ->
// will be "follow_system" only for now
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
}
}
}
var sharedApplication: NextcloudTalkApplication? = null
protected set
//endregion
//region Setters
fun setAppTheme(theme: String) {
when (theme) {
"night_no" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
"night_yes" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
"battery_saver" -> AppCompatDelegate.setDefaultNightMode(
AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY
)
else ->
// will be "follow_system" only for now
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
}
}
}
//endregion
}

View File

@ -25,9 +25,9 @@ import android.text.Editable;
import android.text.Spanned;
import android.widget.EditText;
import com.facebook.widget.text.span.BetterImageSpan;
import com.nextcloud.talk.models.json.mention.Mention;
import com.nextcloud.talk.R;
import com.nextcloud.talk.models.database.UserEntity;
import com.nextcloud.talk.models.json.mention.Mention;
import com.nextcloud.talk.utils.DisplayUtils;
import com.nextcloud.talk.utils.MagicCharPolicy;
import com.nextcloud.talk.utils.text.Spans;
@ -36,44 +36,44 @@ import com.vanniktech.emoji.EmojiRange;
import com.vanniktech.emoji.EmojiUtils;
public class MentionAutocompleteCallback implements AutocompleteCallback<Mention> {
private Context context;
private UserEntity conversationUser;
private EditText editText;
private Context context;
private UserEntity conversationUser;
private EditText editText;
public MentionAutocompleteCallback(Context context, UserEntity conversationUser,
EditText editText) {
this.context = context;
this.conversationUser = conversationUser;
this.editText = editText;
public MentionAutocompleteCallback(Context context, UserEntity conversationUser,
EditText editText) {
this.context = context;
this.conversationUser = conversationUser;
this.editText = editText;
}
@Override
public boolean onPopupItemClicked(Editable editable, Mention item) {
int[] range = MagicCharPolicy.getQueryRange(editable);
if (range == null) return false;
int start = range[0];
int end = range[1];
String replacement = item.getLabel();
StringBuilder replacementStringBuilder = new StringBuilder(item.getLabel());
for (EmojiRange emojiRange : EmojiUtils.emojis(replacement)) {
replacementStringBuilder.delete(emojiRange.start, emojiRange.end);
}
@Override
public boolean onPopupItemClicked(Editable editable, Mention item) {
int[] range = MagicCharPolicy.getQueryRange(editable);
if (range == null) return false;
int start = range[0];
int end = range[1];
String replacement = item.getLabel();
editable.replace(start, end, replacementStringBuilder.toString() + " ");
Spans.MentionChipSpan mentionChipSpan =
new Spans.MentionChipSpan(DisplayUtils.getDrawableForMentionChipSpan(context,
item.getId(), item.getLabel(), conversationUser, item.getSource(),
R.xml.chip_you, editText),
BetterImageSpan.ALIGN_CENTER,
item.getId(), item.getLabel());
editable.setSpan(mentionChipSpan, start, start + replacementStringBuilder.toString().length(),
Spanned.SPAN_INCLUSIVE_INCLUSIVE);
return true;
}
StringBuilder replacementStringBuilder = new StringBuilder(item.getLabel());
for(EmojiRange emojiRange : EmojiUtils.emojis(replacement)) {
replacementStringBuilder.delete(emojiRange.start, emojiRange.end);
}
@Override
public void onPopupVisibilityChanged(boolean shown) {
editable.replace(start, end, replacementStringBuilder.toString() + " ");
Spans.MentionChipSpan mentionChipSpan =
new Spans.MentionChipSpan(DisplayUtils.getDrawableForMentionChipSpan(context,
item.getId(), item.getLabel(), conversationUser, item.getSource(),
R.xml.chip_you, editText),
BetterImageSpan.ALIGN_CENTER,
item.getId(), item.getLabel());
editable.setSpan(mentionChipSpan, start, start + replacementStringBuilder.toString().length(),
Spanned.SPAN_INCLUSIVE_INCLUSIVE);
return true;
}
@Override
public void onPopupVisibilityChanged(boolean shown) {
}
}
}

View File

@ -50,136 +50,143 @@ import java.util.List;
import javax.inject.Inject;
@AutoInjector(NextcloudTalkApplication.class)
public class BrowserFileItem extends AbstractFlexibleItem<BrowserFileItem.ViewHolder> implements IFilterable<String> {
@Inject
Context context;
private BrowserFile browserFile;
private UserEntity activeUser;
private SelectionInterface selectionInterface;
private boolean selected;
public class BrowserFileItem extends AbstractFlexibleItem<BrowserFileItem.ViewHolder>
implements IFilterable<String> {
@Inject
Context context;
private BrowserFile browserFile;
private UserEntity activeUser;
private SelectionInterface selectionInterface;
private boolean selected;
public BrowserFileItem(BrowserFile browserFile, UserEntity activeUser, SelectionInterface selectionInterface) {
this.browserFile = browserFile;
this.activeUser = activeUser;
this.selectionInterface = selectionInterface;
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
public BrowserFileItem(BrowserFile browserFile, UserEntity activeUser,
SelectionInterface selectionInterface) {
this.browserFile = browserFile;
this.activeUser = activeUser;
this.selectionInterface = selectionInterface;
NextcloudTalkApplication.Companion.getSharedApplication()
.getComponentApplication()
.inject(this);
}
@Override
public boolean equals(Object o) {
if (o instanceof BrowserFileItem) {
BrowserFileItem inItem = (BrowserFileItem) o;
return browserFile.getPath().equals(inItem.getModel().getPath());
}
@Override
public boolean equals(Object o) {
if (o instanceof BrowserFileItem) {
BrowserFileItem inItem = (BrowserFileItem) o;
return browserFile.getPath().equals(inItem.getModel().getPath());
return false;
}
public BrowserFile getModel() {
return browserFile;
}
@Override
public int getLayoutRes() {
return R.layout.rv_item_browser_file;
}
@Override
public ViewHolder createViewHolder(View view, FlexibleAdapter<IFlexible> adapter) {
return new ViewHolder(view, adapter);
}
private boolean isSelected() {
return selected;
}
private void setSelected(boolean selected) {
this.selected = selected;
}
@Override
public void bindViewHolder(FlexibleAdapter<IFlexible> adapter, ViewHolder holder, int position,
List<Object> payloads) {
holder.fileIconImageView.setController(null);
if (browserFile.isEncrypted()) {
holder.fileEncryptedImageView.setVisibility(View.VISIBLE);
holder.itemView.setEnabled(false);
holder.itemView.setAlpha(0.38f);
} else {
holder.fileEncryptedImageView.setVisibility(View.GONE);
holder.itemView.setEnabled(true);
holder.itemView.setAlpha(1.0f);
}
if (browserFile.isFavorite()) {
holder.fileFavoriteImageView.setVisibility(View.VISIBLE);
} else {
holder.fileFavoriteImageView.setVisibility(View.GONE);
}
holder.fileIconImageView.getHierarchy()
.setPlaceholderImage(context.getDrawable(
DrawableUtils.INSTANCE.getDrawableResourceIdForMimeType(browserFile.getMimeType())));
if (browserFile.isHasPreview()) {
String path = ApiUtils.getUrlForFilePreviewWithRemotePath(activeUser.getBaseUrl(),
browserFile.getPath(),
context.getResources().getDimensionPixelSize(R.dimen.small_item_height));
if (path.length() > 0) {
DraweeController draweeController = Fresco.newDraweeControllerBuilder()
.setAutoPlayAnimations(true)
.setImageRequest(DisplayUtils.getImageRequestForUrl(path, null))
.build();
holder.fileIconImageView.setController(draweeController);
}
}
holder.filenameTextView.setText(browserFile.getDisplayName());
holder.fileModifiedTextView.setText(String.format(context.getString(R.string.nc_last_modified),
Formatter.formatShortFileSize(context, browserFile.getSize()),
DateUtils.INSTANCE.getLocalDateTimeStringFromTimestamp(
browserFile.getModifiedTimestamp())));
setSelected(selectionInterface.isPathSelected(browserFile.getPath()));
holder.selectFileCheckbox.setChecked(isSelected());
if (!browserFile.isEncrypted()) {
holder.selectFileCheckbox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (((CheckBox) v).isChecked() != isSelected()) {
setSelected(((CheckBox) v).isChecked());
selectionInterface.toggleBrowserItemSelection(browserFile.getPath());
}
}
return false;
});
}
public BrowserFile getModel() {
return browserFile;
}
@Override
public int getLayoutRes() {
return R.layout.rv_item_browser_file;
}
@Override
public ViewHolder createViewHolder(View view, FlexibleAdapter<IFlexible> adapter) {
return new ViewHolder(view, adapter);
}
private boolean isSelected() {
return selected;
}
private void setSelected(boolean selected) {
this.selected = selected;
}
@Override
public void bindViewHolder(FlexibleAdapter<IFlexible> adapter, ViewHolder holder, int position, List<Object> payloads) {
holder.fileIconImageView.setController(null);
if (browserFile.isEncrypted()) {
holder.fileEncryptedImageView.setVisibility(View.VISIBLE);
holder.itemView.setEnabled(false);
holder.itemView.setAlpha(0.38f);
} else {
holder.fileEncryptedImageView.setVisibility(View.GONE);
holder.itemView.setEnabled(true);
holder.itemView.setAlpha(1.0f);
}
if (browserFile.isFavorite()) {
holder.fileFavoriteImageView.setVisibility(View.VISIBLE);
} else {
holder.fileFavoriteImageView.setVisibility(View.GONE);
}
holder.fileIconImageView.getHierarchy().setPlaceholderImage(context.getDrawable(DrawableUtils.INSTANCE.getDrawableResourceIdForMimeType(browserFile.getMimeType())));
if (browserFile.isHasPreview()) {
String path = ApiUtils.getUrlForFilePreviewWithRemotePath(activeUser.getBaseUrl(),
browserFile.getPath(),
context.getResources().getDimensionPixelSize(R.dimen.small_item_height));
if (path.length() > 0) {
DraweeController draweeController = Fresco.newDraweeControllerBuilder()
.setAutoPlayAnimations(true)
.setImageRequest(DisplayUtils.getImageRequestForUrl(path, null))
.build();
holder.fileIconImageView.setController(draweeController);
}
}
holder.filenameTextView.setText(browserFile.getDisplayName());
holder.fileModifiedTextView.setText(String.format(context.getString(R.string.nc_last_modified),
Formatter.formatShortFileSize(context, browserFile.getSize()),
DateUtils.INSTANCE.getLocalDateTimeStringFromTimestamp(browserFile.getModifiedTimestamp())));
setSelected(selectionInterface.isPathSelected(browserFile.getPath()));
holder.selectFileCheckbox.setChecked(isSelected());
if (!browserFile.isEncrypted()) {
holder.selectFileCheckbox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (((CheckBox) v).isChecked() != isSelected()) {
setSelected(((CheckBox) v).isChecked());
selectionInterface.toggleBrowserItemSelection(browserFile.getPath());
}
}
});
}
holder.filenameTextView.setSelected(true);
holder.fileModifiedTextView.setSelected(true);
}
@Override
public boolean filter(String constraint) {
return false;
}
static class ViewHolder extends FlexibleViewHolder {
@BindView(R.id.file_icon)
public SimpleDraweeView fileIconImageView;
@BindView(R.id.file_modified_info)
public TextView fileModifiedTextView;
@BindView(R.id.filename_text_view)
public TextView filenameTextView;
@BindView(R.id.select_file_checkbox)
public CheckBox selectFileCheckbox;
@BindView(R.id.fileEncryptedImageView)
public ImageView fileEncryptedImageView;
@BindView(R.id.fileFavoriteImageView)
public ImageView fileFavoriteImageView;
ViewHolder(View view, FlexibleAdapter adapter) {
super(view, adapter);
ButterKnife.bind(this, view);
}
holder.filenameTextView.setSelected(true);
holder.fileModifiedTextView.setSelected(true);
}
@Override
public boolean filter(String constraint) {
return false;
}
static class ViewHolder extends FlexibleViewHolder {
@BindView(R.id.file_icon)
public SimpleDraweeView fileIconImageView;
@BindView(R.id.file_modified_info)
public TextView fileModifiedTextView;
@BindView(R.id.filename_text_view)
public TextView filenameTextView;
@BindView(R.id.select_file_checkbox)
public CheckBox selectFileCheckbox;
@BindView(R.id.fileEncryptedImageView)
public ImageView fileEncryptedImageView;
@BindView(R.id.fileFavoriteImageView)
public ImageView fileFavoriteImageView;
ViewHolder(View view, FlexibleAdapter adapter) {
super(view, adapter);
ButterKnife.bind(this, view);
}
}
}

View File

@ -71,278 +71,281 @@ import org.parceler.Parcels;
@AutoInjector(NextcloudTalkApplication.class)
public class BrowserController extends BaseController implements ListingInterface,
FlexibleAdapter.OnItemClickListener, SelectionInterface {
private final Set<String> selectedPaths;
@Inject
UserUtils userUtils;
@BindView(R.id.recyclerView)
RecyclerView recyclerView;
@BindView(R.id.fast_scroller)
FastScroller fastScroller;
@BindView(R.id.action_back)
BottomNavigationItemView backMenuItem;
@BindView(R.id.action_refresh)
BottomNavigationItemView actionRefreshMenuItem;
@Inject
Context context;
@Inject
OkHttpClient okHttpClient;
FlexibleAdapter.OnItemClickListener, SelectionInterface {
private final Set<String> selectedPaths;
@Inject
UserUtils userUtils;
@BindView(R.id.recyclerView)
RecyclerView recyclerView;
@BindView(R.id.fast_scroller)
FastScroller fastScroller;
@BindView(R.id.action_back)
BottomNavigationItemView backMenuItem;
@BindView(R.id.action_refresh)
BottomNavigationItemView actionRefreshMenuItem;
@Inject
Context context;
@Inject
OkHttpClient okHttpClient;
private MenuItem filesSelectionDoneMenuItem;
private RecyclerView.LayoutManager layoutManager;
private MenuItem filesSelectionDoneMenuItem;
private RecyclerView.LayoutManager layoutManager;
private FlexibleAdapter<AbstractFlexibleItem> adapter;
private List<AbstractFlexibleItem> recyclerViewItems = new ArrayList<>();
private FlexibleAdapter<AbstractFlexibleItem> adapter;
private List<AbstractFlexibleItem> recyclerViewItems = new ArrayList<>();
private ListingAbstractClass listingAbstractClass;
private BrowserType browserType;
private String currentPath;
private UserEntity activeUser;
private String roomToken;
private ListingAbstractClass listingAbstractClass;
private BrowserType browserType;
private String currentPath;
private UserEntity activeUser;
private String roomToken;
public BrowserController(Bundle args) {
super();
setHasOptionsMenu(true);
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
browserType = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_BROWSER_TYPE()));
activeUser = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY()));
roomToken = args.getString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN());
public BrowserController(Bundle args) {
super();
setHasOptionsMenu(true);
NextcloudTalkApplication.Companion.getSharedApplication()
.getComponentApplication()
.inject(this);
browserType = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_BROWSER_TYPE()));
activeUser = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY()));
roomToken = args.getString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN());
currentPath = "/";
if (BrowserType.DAV_BROWSER.equals(browserType)) {
listingAbstractClass = new DavListing(this);
} else {
//listingAbstractClass = new LocalListing(this);
currentPath = "/";
if (BrowserType.DAV_BROWSER.equals(browserType)) {
listingAbstractClass = new DavListing(this);
} else {
//listingAbstractClass = new LocalListing(this);
}
selectedPaths = Collections.synchronizedSet(new TreeSet<>());
}
@Override
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
return inflater.inflate(R.layout.controller_browser, container, false);
}
@Override
protected void onViewBound(@NonNull View view) {
super.onViewBound(view);
if (adapter == null) {
adapter = new FlexibleAdapter<>(recyclerViewItems, context, false);
}
changeEnabledStatusForBarItems(true);
prepareViews();
}
private void onFileSelectionDone() {
synchronized (selectedPaths) {
Iterator<String> iterator = selectedPaths.iterator();
List<String> paths = new ArrayList<>();
Data data;
OneTimeWorkRequest shareWorker;
while (iterator.hasNext()) {
String path = iterator.next();
paths.add(path);
iterator.remove();
if (paths.size() == 10 || !iterator.hasNext()) {
data = new Data.Builder()
.putLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), activeUser.getId())
.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), roomToken)
.putStringArray(BundleKeys.INSTANCE.getKEY_FILE_PATHS(), paths.toArray(new String[0]))
.build();
shareWorker = new OneTimeWorkRequest.Builder(ShareOperationWorker.class)
.setInputData(data)
.build();
WorkManager.getInstance().enqueue(shareWorker);
paths = new ArrayList<>();
}
selectedPaths = Collections.synchronizedSet(new TreeSet<>());
}
}
@Override
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
return inflater.inflate(R.layout.controller_browser, container, false);
getRouter().popCurrentController();
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.menu_share_files, menu);
filesSelectionDoneMenuItem = menu.findItem(R.id.files_selection_done);
filesSelectionDoneMenuItem.setVisible(selectedPaths.size() > 0);
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.files_selection_done:
onFileSelectionDone();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
protected void onAttach(@NonNull View view) {
super.onAttach(view);
refreshCurrentPath();
}
@Override
public void onDestroy() {
super.onDestroy();
listingAbstractClass.tearDown();
}
@Override
public String getTitle() {
return currentPath;
}
@OnClick(R.id.action_back)
void goBack() {
fetchPath(new File(currentPath).getParent());
}
@OnClick(R.id.action_refresh)
void refreshCurrentPath() {
fetchPath(currentPath);
}
@SuppressLint("RestrictedApi")
private void changeEnabledStatusForBarItems(boolean shouldBeEnabled) {
if (actionRefreshMenuItem != null) {
actionRefreshMenuItem.setEnabled(shouldBeEnabled);
}
@Override
protected void onViewBound(@NonNull View view) {
super.onViewBound(view);
if (adapter == null) {
adapter = new FlexibleAdapter<>(recyclerViewItems, context, false);
}
if (backMenuItem != null) {
backMenuItem.setEnabled(shouldBeEnabled && !currentPath.equals("/"));
}
}
changeEnabledStatusForBarItems(true);
prepareViews();
private void fetchPath(String path) {
listingAbstractClass.cancelAllJobs();
changeEnabledStatusForBarItems(false);
listingAbstractClass.getFiles(path, activeUser,
BrowserType.DAV_BROWSER.equals(browserType) ? okHttpClient : null);
}
@Override
public void listingResult(DavResponse davResponse) {
adapter.clear();
List<AbstractFlexibleItem> fileBrowserItems = new ArrayList<>();
if (davResponse.getData() != null) {
final List<BrowserFile> objectList = (List<BrowserFile>) davResponse.getData();
currentPath = objectList.get(0).getPath();
if (getActivity() != null) {
getActivity().runOnUiThread(() -> setTitle());
}
for (int i = 1; i < objectList.size(); i++) {
fileBrowserItems.add(new BrowserFileItem(objectList.get(i), activeUser, this));
}
}
private void onFileSelectionDone() {
synchronized (selectedPaths) {
Iterator<String> iterator = selectedPaths.iterator();
List<String> paths = new ArrayList<>();
Data data;
OneTimeWorkRequest shareWorker;
while (iterator.hasNext()) {
String path = iterator.next();
paths.add(path);
iterator.remove();
if (paths.size() == 10 || !iterator.hasNext()) {
data = new Data.Builder()
.putLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), activeUser.getId())
.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), roomToken)
.putStringArray(BundleKeys.INSTANCE.getKEY_FILE_PATHS(), paths.toArray(new String[0]))
.build();
shareWorker = new OneTimeWorkRequest.Builder(ShareOperationWorker.class)
.setInputData(data)
.build();
WorkManager.getInstance().enqueue(shareWorker);
paths = new ArrayList<>();
}
}
}
getRouter().popCurrentController();
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.menu_share_files, menu);
filesSelectionDoneMenuItem = menu.findItem(R.id.files_selection_done);
filesSelectionDoneMenuItem.setVisible(selectedPaths.size() > 0);
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.files_selection_done:
onFileSelectionDone();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
protected void onAttach(@NonNull View view) {
super.onAttach(view);
refreshCurrentPath();
}
@Override
public void onDestroy() {
super.onDestroy();
listingAbstractClass.tearDown();
}
@Override
public String getTitle() {
return currentPath;
}
@OnClick(R.id.action_back)
void goBack() {
fetchPath(new File(currentPath).getParent());
}
@OnClick(R.id.action_refresh)
void refreshCurrentPath() {
fetchPath(currentPath);
}
@SuppressLint("RestrictedApi")
private void changeEnabledStatusForBarItems(boolean shouldBeEnabled) {
if (actionRefreshMenuItem != null) {
actionRefreshMenuItem.setEnabled(shouldBeEnabled);
}
if (backMenuItem != null) {
backMenuItem.setEnabled(shouldBeEnabled && !currentPath.equals("/"));
}
}
private void fetchPath(String path) {
listingAbstractClass.cancelAllJobs();
changeEnabledStatusForBarItems(false);
listingAbstractClass.getFiles(path, activeUser, BrowserType.DAV_BROWSER.equals(browserType) ? okHttpClient : null);
}
@Override
public void listingResult(DavResponse davResponse) {
adapter.clear();
List<AbstractFlexibleItem> fileBrowserItems = new ArrayList<>();
if (davResponse.getData() != null) {
final List<BrowserFile> objectList = (List<BrowserFile>) davResponse.getData();
currentPath = objectList.get(0).getPath();
if (getActivity() != null) {
getActivity().runOnUiThread(() -> setTitle());
}
for (int i = 1; i < objectList.size(); i++) {
fileBrowserItems.add(new BrowserFileItem(objectList.get(i), activeUser, this));
}
}
adapter.addItems(0, fileBrowserItems);
if (getActivity() != null) {
getActivity().runOnUiThread(() -> {
adapter.notifyDataSetChanged();
changeEnabledStatusForBarItems(true);
});
}
}
private boolean shouldPathBeSelectedDueToParent(String currentPath) {
if (selectedPaths.size() > 0) {
File file = new File(currentPath);
if (!file.getParent().equals("/")) {
while (file.getParent() != null) {
String parent = file.getParent();
if (new File(file.getParent()).getParent() != null) {
parent += "/";
}
if (selectedPaths.contains(parent)) {
return true;
}
file = new File(file.getParent());
}
}
}
return false;
}
private void checkAndRemoveAnySelectedParents(String currentPath) {
File file = new File(currentPath);
selectedPaths.remove(currentPath);
while (file.getParent() != null) {
selectedPaths.remove(file.getParent() + "/");
file = new File(file.getParent());
}
adapter.addItems(0, fileBrowserItems);
if (getActivity() != null) {
getActivity().runOnUiThread(() -> {
adapter.notifyDataSetChanged();
changeEnabledStatusForBarItems(true);
});
}
}
@Override
public boolean onItemClick(View view, int position) {
BrowserFile browserFile = ((BrowserFileItem) adapter.getItem(position)).getModel();
if ("inode/directory".equals((browserFile.getMimeType()))) {
fetchPath(browserFile.getPath());
private boolean shouldPathBeSelectedDueToParent(String currentPath) {
if (selectedPaths.size() > 0) {
File file = new File(currentPath);
if (!file.getParent().equals("/")) {
while (file.getParent() != null) {
String parent = file.getParent();
if (new File(file.getParent()).getParent() != null) {
parent += "/";
}
if (selectedPaths.contains(parent)) {
return true;
}
}
return false;
file = new File(file.getParent());
}
}
}
private void prepareViews() {
if (getActivity() != null) {
layoutManager = new SmoothScrollLinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);
recyclerView.setAdapter(adapter);
return false;
}
adapter.setFastScroller(fastScroller);
adapter.addListener(this);
fastScroller.setBubbleTextCreator(position -> {
IFlexible abstractFlexibleItem = adapter.getItem(position);
if (abstractFlexibleItem instanceof BrowserFileItem) {
return String.valueOf(((BrowserFileItem) adapter.getItem(position)).getModel().getDisplayName().charAt(0));
} else {
return "";
}
});
}
private void checkAndRemoveAnySelectedParents(String currentPath) {
File file = new File(currentPath);
selectedPaths.remove(currentPath);
while (file.getParent() != null) {
selectedPaths.remove(file.getParent() + "/");
file = new File(file.getParent());
}
@SuppressLint("RestrictedApi")
@Override
public void toggleBrowserItemSelection(String path) {
if (selectedPaths.contains(path) || shouldPathBeSelectedDueToParent(path)) {
checkAndRemoveAnySelectedParents(path);
adapter.notifyDataSetChanged();
}
@Override
public boolean onItemClick(View view, int position) {
BrowserFile browserFile = ((BrowserFileItem) adapter.getItem(position)).getModel();
if ("inode/directory".equals((browserFile.getMimeType()))) {
fetchPath(browserFile.getPath());
return true;
}
return false;
}
private void prepareViews() {
if (getActivity() != null) {
layoutManager = new SmoothScrollLinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);
recyclerView.setAdapter(adapter);
adapter.setFastScroller(fastScroller);
adapter.addListener(this);
fastScroller.setBubbleTextCreator(position -> {
IFlexible abstractFlexibleItem = adapter.getItem(position);
if (abstractFlexibleItem instanceof BrowserFileItem) {
return String.valueOf(
((BrowserFileItem) adapter.getItem(position)).getModel().getDisplayName().charAt(0));
} else {
// TOOD: if it's a folder, remove all the children we added manually
selectedPaths.add(path);
return "";
}
});
}
}
filesSelectionDoneMenuItem.setVisible(selectedPaths.size() > 0);
@SuppressLint("RestrictedApi")
@Override
public void toggleBrowserItemSelection(String path) {
if (selectedPaths.contains(path) || shouldPathBeSelectedDueToParent(path)) {
checkAndRemoveAnySelectedParents(path);
} else {
// TOOD: if it's a folder, remove all the children we added manually
selectedPaths.add(path);
}
@Override
public boolean isPathSelected(String path) {
return (selectedPaths.contains(path) || shouldPathBeSelectedDueToParent(path));
}
filesSelectionDoneMenuItem.setVisible(selectedPaths.size() > 0);
}
@Parcel
public enum BrowserType {
FILE_BROWSER,
DAV_BROWSER,
}
@Override
public boolean isPathSelected(String path) {
return (selectedPaths.contains(path) || shouldPathBeSelectedDueToParent(path));
}
@Parcel
public enum BrowserType {
FILE_BROWSER,
DAV_BROWSER,
}
}

View File

@ -23,5 +23,5 @@ package com.nextcloud.talk.components.filebrowser.interfaces;
import com.nextcloud.talk.components.filebrowser.models.DavResponse;
public interface ListingInterface {
void listingResult(DavResponse davResponse);
void listingResult(DavResponse davResponse);
}

View File

@ -43,67 +43,68 @@ import org.parceler.Parcel;
@JsonObject
@Parcel
public class BrowserFile {
public String path;
public String displayName;
public String mimeType;
public long modifiedTimestamp;
public long size;
public boolean isFile;
// Used for remote files
public String remoteId;
public boolean hasPreview;
public boolean favorite;
public boolean encrypted;
public String path;
public String displayName;
public String mimeType;
public long modifiedTimestamp;
public long size;
public boolean isFile;
// Used for remote files
public String remoteId;
public boolean hasPreview;
public boolean favorite;
public boolean encrypted;
public static BrowserFile getModelFromResponse(Response response, String remotePath) {
BrowserFile browserFile = new BrowserFile();
browserFile.setPath(Uri.decode(remotePath));
browserFile.setDisplayName(Uri.decode(new File(remotePath).getName()));
final List<Property> properties = response.getProperties();
public static BrowserFile getModelFromResponse(Response response, String remotePath) {
BrowserFile browserFile = new BrowserFile();
browserFile.setPath(Uri.decode(remotePath));
browserFile.setDisplayName(Uri.decode(new File(remotePath).getName()));
final List<Property> properties = response.getProperties();
for (Property property : properties) {
if (property instanceof OCId) {
browserFile.setRemoteId(((OCId) property).getOcId());
}
for (Property property : properties) {
if (property instanceof OCId) {
browserFile.setRemoteId(((OCId) property).getOcId());
}
if (property instanceof ResourceType) {
browserFile.isFile =
!(((ResourceType) property).getTypes().contains(ResourceType.Companion.getCOLLECTION()));
}
if (property instanceof ResourceType) {
browserFile.isFile =
!(((ResourceType) property).getTypes()
.contains(ResourceType.Companion.getCOLLECTION()));
}
if (property instanceof GetLastModified) {
browserFile.setModifiedTimestamp(((GetLastModified) property).getLastModified());
}
if (property instanceof GetLastModified) {
browserFile.setModifiedTimestamp(((GetLastModified) property).getLastModified());
}
if (property instanceof GetContentType) {
browserFile.setMimeType(((GetContentType) property).getType());
}
if (property instanceof GetContentType) {
browserFile.setMimeType(((GetContentType) property).getType());
}
if (property instanceof OCSize) {
browserFile.setSize(((OCSize) property).getOcSize());
}
if (property instanceof OCSize) {
browserFile.setSize(((OCSize) property).getOcSize());
}
if (property instanceof NCPreview) {
browserFile.setHasPreview(((NCPreview) property).isNcPreview());
}
if (property instanceof NCPreview) {
browserFile.setHasPreview(((NCPreview) property).isNcPreview());
}
if (property instanceof OCFavorite) {
browserFile.setFavorite(((OCFavorite) property).isOcFavorite());
}
if (property instanceof OCFavorite) {
browserFile.setFavorite(((OCFavorite) property).isOcFavorite());
}
if (property instanceof DisplayName) {
browserFile.setDisplayName(((DisplayName) property).getDisplayName());
}
if (property instanceof DisplayName) {
browserFile.setDisplayName(((DisplayName) property).getDisplayName());
}
if (property instanceof NCEncrypted) {
browserFile.setEncrypted(((NCEncrypted) property).isNcEncrypted());
}
}
if (TextUtils.isEmpty(browserFile.getMimeType()) && !browserFile.isFile()) {
browserFile.setMimeType("inode/directory");
}
return browserFile;
if (property instanceof NCEncrypted) {
browserFile.setEncrypted(((NCEncrypted) property).isNcEncrypted());
}
}
if (TextUtils.isEmpty(browserFile.getMimeType()) && !browserFile.isFile()) {
browserFile.setMimeType("inode/directory");
}
return browserFile;
}
}

View File

@ -25,6 +25,6 @@ import lombok.Data;
@Data
public class DavResponse {
Response response;
Object data;
Response response;
Object data;
}

View File

@ -34,39 +34,40 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
public class NCEncrypted implements Property {
public static final Name NAME = new Name(DavUtils.NC_NAMESPACE, DavUtils.EXTENDED_PROPERTY_IS_ENCRYPTED);
public static final Name NAME =
new Name(DavUtils.NC_NAMESPACE, DavUtils.EXTENDED_PROPERTY_IS_ENCRYPTED);
@Getter
@Setter
private boolean ncEncrypted;
@Getter
@Setter
private boolean ncEncrypted;
private NCEncrypted(boolean isEncrypted) {
ncEncrypted = isEncrypted;
private NCEncrypted(boolean isEncrypted) {
ncEncrypted = isEncrypted;
}
public static class Factory implements PropertyFactory {
@Nullable
@Override
public Property create(@NotNull XmlPullParser xmlPullParser) {
try {
String text = XmlUtils.INSTANCE.readText(xmlPullParser);
if (!TextUtils.isEmpty(text)) {
return new NCEncrypted(Boolean.parseBoolean(text));
}
} catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
return new NCEncrypted(false);
}
public static class Factory implements PropertyFactory {
@Nullable
@Override
public Property create(@NotNull XmlPullParser xmlPullParser) {
try {
String text = XmlUtils.INSTANCE.readText(xmlPullParser);
if (!TextUtils.isEmpty(text)) {
return new NCEncrypted(Boolean.parseBoolean(text));
}
} catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
return new NCEncrypted(false);
}
@NotNull
@Override
public Name getName() {
return NAME;
}
@NotNull
@Override
public Name getName() {
return NAME;
}
}
}

View File

@ -34,39 +34,40 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
public class NCPreview implements Property {
public static final Property.Name NAME = new Property.Name(DavUtils.NC_NAMESPACE, DavUtils.EXTENDED_PROPERTY_HAS_PREVIEW);
public static final Property.Name NAME =
new Property.Name(DavUtils.NC_NAMESPACE, DavUtils.EXTENDED_PROPERTY_HAS_PREVIEW);
@Getter
@Setter
private boolean ncPreview;
@Getter
@Setter
private boolean ncPreview;
private NCPreview(boolean hasPreview) {
ncPreview = hasPreview;
private NCPreview(boolean hasPreview) {
ncPreview = hasPreview;
}
public static class Factory implements PropertyFactory {
@Nullable
@Override
public Property create(@NotNull XmlPullParser xmlPullParser) {
try {
String text = XmlUtils.INSTANCE.readText(xmlPullParser);
if (!TextUtils.isEmpty(text)) {
return new NCPreview(Boolean.parseBoolean(text));
}
} catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
return new OCFavorite(false);
}
public static class Factory implements PropertyFactory {
@Nullable
@Override
public Property create(@NotNull XmlPullParser xmlPullParser) {
try {
String text = XmlUtils.INSTANCE.readText(xmlPullParser);
if (!TextUtils.isEmpty(text)) {
return new NCPreview(Boolean.parseBoolean(text));
}
} catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
return new OCFavorite(false);
}
@NotNull
@Override
public Property.Name getName() {
return NAME;
}
@NotNull
@Override
public Property.Name getName() {
return NAME;
}
}
}

View File

@ -34,39 +34,40 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
public class OCFavorite implements Property {
public static final Property.Name NAME = new Property.Name(DavUtils.OC_NAMESPACE, DavUtils.EXTENDED_PROPERTY_FAVORITE);
public static final Property.Name NAME =
new Property.Name(DavUtils.OC_NAMESPACE, DavUtils.EXTENDED_PROPERTY_FAVORITE);
@Getter
@Setter
private boolean ocFavorite;
@Getter
@Setter
private boolean ocFavorite;
OCFavorite(boolean isFavorite) {
ocFavorite = isFavorite;
OCFavorite(boolean isFavorite) {
ocFavorite = isFavorite;
}
public static class Factory implements PropertyFactory {
@Nullable
@Override
public Property create(@NotNull XmlPullParser xmlPullParser) {
try {
String text = XmlUtils.INSTANCE.readText(xmlPullParser);
if (!TextUtils.isEmpty(text)) {
return new OCFavorite(Boolean.parseBoolean(text));
}
} catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
return new OCFavorite(false);
}
public static class Factory implements PropertyFactory {
@Nullable
@Override
public Property create(@NotNull XmlPullParser xmlPullParser) {
try {
String text = XmlUtils.INSTANCE.readText(xmlPullParser);
if (!TextUtils.isEmpty(text)) {
return new OCFavorite(Boolean.parseBoolean(text));
}
} catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
return new OCFavorite(false);
}
@NotNull
@Override
public Property.Name getName() {
return NAME;
}
@NotNull
@Override
public Property.Name getName() {
return NAME;
}
}
}

View File

@ -34,39 +34,40 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
public class OCId implements Property {
public static final Name NAME = new Name(DavUtils.OC_NAMESPACE, DavUtils.EXTENDED_PROPERTY_NAME_REMOTE_ID);
public static final Name NAME =
new Name(DavUtils.OC_NAMESPACE, DavUtils.EXTENDED_PROPERTY_NAME_REMOTE_ID);
@Getter
@Setter
private String ocId;
@Getter
@Setter
private String ocId;
private OCId(String id) {
ocId = id;
private OCId(String id) {
ocId = id;
}
public static class Factory implements PropertyFactory {
@Nullable
@Override
public Property create(@NotNull XmlPullParser xmlPullParser) {
try {
String text = XmlUtils.INSTANCE.readText(xmlPullParser);
if (!TextUtils.isEmpty(text)) {
return new OCId(text);
}
} catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
return new OCId("");
}
public static class Factory implements PropertyFactory {
@Nullable
@Override
public Property create(@NotNull XmlPullParser xmlPullParser) {
try {
String text = XmlUtils.INSTANCE.readText(xmlPullParser);
if (!TextUtils.isEmpty(text)) {
return new OCId(text);
}
} catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
return new OCId("");
}
@NotNull
@Override
public Name getName() {
return NAME;
}
@NotNull
@Override
public Name getName() {
return NAME;
}
}
}

View File

@ -34,39 +34,40 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
public class OCSize implements Property {
public static final Property.Name NAME = new Property.Name(DavUtils.OC_NAMESPACE, DavUtils.EXTENDED_PROPERTY_NAME_SIZE);
public static final Property.Name NAME =
new Property.Name(DavUtils.OC_NAMESPACE, DavUtils.EXTENDED_PROPERTY_NAME_SIZE);
@Getter
@Setter
private long ocSize;
@Getter
@Setter
private long ocSize;
private OCSize(long size) {
ocSize = size;
private OCSize(long size) {
ocSize = size;
}
public static class Factory implements PropertyFactory {
@Nullable
@Override
public Property create(@NotNull XmlPullParser xmlPullParser) {
try {
String text = XmlUtils.INSTANCE.readText(xmlPullParser);
if (!TextUtils.isEmpty(text)) {
return new OCSize(Long.parseLong(text));
}
} catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
return new OCSize(-1);
}
public static class Factory implements PropertyFactory {
@Nullable
@Override
public Property create(@NotNull XmlPullParser xmlPullParser) {
try {
String text = XmlUtils.INSTANCE.readText(xmlPullParser);
if (!TextUtils.isEmpty(text)) {
return new OCSize(Long.parseLong(text));
}
} catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
return new OCSize(-1);
}
@NotNull
@Override
public Name getName() {
return NAME;
}
@NotNull
@Override
public Name getName() {
return NAME;
}
}
}

View File

@ -33,36 +33,36 @@ import java.util.concurrent.Callable;
import okhttp3.OkHttpClient;
public class DavListing extends ListingAbstractClass {
private DavResponse davResponse = new DavResponse();
private DavResponse davResponse = new DavResponse();
public DavListing(ListingInterface listingInterface) {
super(listingInterface);
}
public DavListing(ListingInterface listingInterface) {
super(listingInterface);
}
@Override
public void getFiles(String path, UserEntity currentUser, @Nullable OkHttpClient okHttpClient) {
Single.fromCallable(new Callable<ReadFilesystemOperation>() {
@Override
public ReadFilesystemOperation call() {
return new ReadFilesystemOperation(okHttpClient, currentUser, path, 1);
}
}).subscribeOn(Schedulers.io())
.subscribe(new SingleObserver<ReadFilesystemOperation>() {
@Override
public void onSubscribe(Disposable d) {
@Override
public void getFiles(String path, UserEntity currentUser, @Nullable OkHttpClient okHttpClient) {
Single.fromCallable(new Callable<ReadFilesystemOperation>() {
@Override
public ReadFilesystemOperation call() {
return new ReadFilesystemOperation(okHttpClient, currentUser, path, 1);
}
}).subscribeOn(Schedulers.io())
.subscribe(new SingleObserver<ReadFilesystemOperation>() {
@Override
public void onSubscribe(Disposable d) {
}
}
@Override
public void onSuccess(ReadFilesystemOperation readFilesystemOperation) {
davResponse = readFilesystemOperation.readRemotePath();
listingInterface.listingResult(davResponse);
}
@Override
public void onSuccess(ReadFilesystemOperation readFilesystemOperation) {
davResponse = readFilesystemOperation.readRemotePath();
listingInterface.listingResult(davResponse);
}
@Override
public void onError(Throwable e) {
listingInterface.listingResult(davResponse);
}
});
}
@Override
public void onError(Throwable e) {
listingInterface.listingResult(davResponse);
}
});
}
}

View File

@ -27,22 +27,23 @@ import com.nextcloud.talk.models.database.UserEntity;
import okhttp3.OkHttpClient;
public abstract class ListingAbstractClass {
Handler handler;
ListingInterface listingInterface;
Handler handler;
ListingInterface listingInterface;
ListingAbstractClass(ListingInterface listingInterface) {
handler = new Handler();
this.listingInterface = listingInterface;
}
ListingAbstractClass(ListingInterface listingInterface) {
handler = new Handler();
this.listingInterface = listingInterface;
}
public abstract void getFiles(String path, UserEntity currentUser, @Nullable OkHttpClient okHttpClient);
public abstract void getFiles(String path, UserEntity currentUser,
@Nullable OkHttpClient okHttpClient);
public void cancelAllJobs() {
handler.removeCallbacksAndMessages(null);
}
public void cancelAllJobs() {
handler.removeCallbacksAndMessages(null);
}
public void tearDown() {
cancelAllJobs();
handler = null;
}
public void tearDown() {
cancelAllJobs();
handler = null;
}
}

View File

@ -42,78 +42,76 @@ import java.util.List;
import java.util.Map;
public class DavUtils {
public static final String OC_NAMESPACE = "http://owncloud.org/ns";
public static final String NC_NAMESPACE = "http://nextcloud.org/ns";
public static final String DAV_PATH = "/remote.php/dav/files/";
public static final String OC_NAMESPACE = "http://owncloud.org/ns";
public static final String NC_NAMESPACE = "http://nextcloud.org/ns";
public static final String DAV_PATH = "/remote.php/dav/files/";
public static final String EXTENDED_PROPERTY_NAME_PERMISSIONS = "permissions";
public static final String EXTENDED_PROPERTY_NAME_REMOTE_ID = "id";
public static final String EXTENDED_PROPERTY_NAME_SIZE = "size";
public static final String EXTENDED_PROPERTY_FAVORITE = "favorite";
public static final String EXTENDED_PROPERTY_IS_ENCRYPTED = "is-encrypted";
public static final String EXTENDED_PROPERTY_MOUNT_TYPE = "mount-type";
public static final String EXTENDED_PROPERTY_OWNER_ID = "owner-id";
public static final String EXTENDED_PROPERTY_OWNER_DISPLAY_NAME = "owner-display-name";
public static final String EXTENDED_PROPERTY_UNREAD_COMMENTS = "comments-unread";
public static final String EXTENDED_PROPERTY_HAS_PREVIEW = "has-preview";
public static final String EXTENDED_PROPERTY_NOTE = "note";
public static final String TRASHBIN_FILENAME = "trashbin-filename";
public static final String TRASHBIN_ORIGINAL_LOCATION = "trashbin-original-location";
public static final String TRASHBIN_DELETION_TIME = "trashbin-deletion-time";
public static final String EXTENDED_PROPERTY_NAME_PERMISSIONS = "permissions";
public static final String EXTENDED_PROPERTY_NAME_REMOTE_ID = "id";
public static final String EXTENDED_PROPERTY_NAME_SIZE = "size";
public static final String EXTENDED_PROPERTY_FAVORITE = "favorite";
public static final String EXTENDED_PROPERTY_IS_ENCRYPTED = "is-encrypted";
public static final String EXTENDED_PROPERTY_MOUNT_TYPE = "mount-type";
public static final String EXTENDED_PROPERTY_OWNER_ID = "owner-id";
public static final String EXTENDED_PROPERTY_OWNER_DISPLAY_NAME = "owner-display-name";
public static final String EXTENDED_PROPERTY_UNREAD_COMMENTS = "comments-unread";
public static final String EXTENDED_PROPERTY_HAS_PREVIEW = "has-preview";
public static final String EXTENDED_PROPERTY_NOTE = "note";
public static final String TRASHBIN_FILENAME = "trashbin-filename";
public static final String TRASHBIN_ORIGINAL_LOCATION = "trashbin-original-location";
public static final String TRASHBIN_DELETION_TIME = "trashbin-deletion-time";
public static final String PROPERTY_QUOTA_USED_BYTES = "quota-used-bytes";
public static final String PROPERTY_QUOTA_AVAILABLE_BYTES = "quota-available-bytes";
public static final String PROPERTY_QUOTA_USED_BYTES = "quota-used-bytes";
public static final String PROPERTY_QUOTA_AVAILABLE_BYTES = "quota-available-bytes";
static Property.Name[] getAllPropSet() {
List<Property.Name> propSet = new ArrayList<>();
static Property.Name[] getAllPropSet() {
List<Property.Name> propSet = new ArrayList<>();
propSet.add(DisplayName.NAME);
propSet.add(GetContentType.NAME);
propSet.add(GetContentLength.NAME);
propSet.add(GetContentType.NAME);
propSet.add(GetContentLength.NAME);
propSet.add(GetLastModified.NAME);
propSet.add(CreationDate.NAME);
propSet.add(GetETag.NAME);
propSet.add(ResourceType.NAME);
propSet.add(DisplayName.NAME);
propSet.add(GetContentType.NAME);
propSet.add(GetContentLength.NAME);
propSet.add(GetContentType.NAME);
propSet.add(GetContentLength.NAME);
propSet.add(GetLastModified.NAME);
propSet.add(CreationDate.NAME);
propSet.add(GetETag.NAME);
propSet.add(ResourceType.NAME);
propSet.add(new Property.Name(OC_NAMESPACE, EXTENDED_PROPERTY_NAME_PERMISSIONS));
propSet.add(OCId.NAME);
propSet.add(OCSize.NAME);
propSet.add(OCFavorite.NAME);
propSet.add(new Property.Name(OC_NAMESPACE, EXTENDED_PROPERTY_OWNER_ID));
propSet.add(new Property.Name(OC_NAMESPACE, EXTENDED_PROPERTY_OWNER_DISPLAY_NAME));
propSet.add(new Property.Name(OC_NAMESPACE, EXTENDED_PROPERTY_UNREAD_COMMENTS));
propSet.add(new Property.Name(OC_NAMESPACE, EXTENDED_PROPERTY_NAME_PERMISSIONS));
propSet.add(OCId.NAME);
propSet.add(OCSize.NAME);
propSet.add(OCFavorite.NAME);
propSet.add(new Property.Name(OC_NAMESPACE, EXTENDED_PROPERTY_OWNER_ID));
propSet.add(new Property.Name(OC_NAMESPACE, EXTENDED_PROPERTY_OWNER_DISPLAY_NAME));
propSet.add(new Property.Name(OC_NAMESPACE, EXTENDED_PROPERTY_UNREAD_COMMENTS));
propSet.add(NCEncrypted.NAME);
propSet.add(new Property.Name(NC_NAMESPACE, EXTENDED_PROPERTY_MOUNT_TYPE));
propSet.add(NCPreview.NAME);
propSet.add(new Property.Name(NC_NAMESPACE, EXTENDED_PROPERTY_NOTE));
propSet.add(NCEncrypted.NAME);
propSet.add(new Property.Name(NC_NAMESPACE, EXTENDED_PROPERTY_MOUNT_TYPE));
propSet.add(NCPreview.NAME);
propSet.add(new Property.Name(NC_NAMESPACE, EXTENDED_PROPERTY_NOTE));
return propSet.toArray(new Property.Name[0]);
return propSet.toArray(new Property.Name[0]);
}
public static void registerCustomFactories() {
PropertyRegistry propertyRegistry = PropertyRegistry.INSTANCE;
try {
Field factories = propertyRegistry.getClass().getDeclaredField("factories");
factories.setAccessible(true);
Map<Property.Name, PropertyFactory> reflectionMap = (HashMap<Property.Name,
PropertyFactory>) factories.get(propertyRegistry);
reflectionMap.put(OCId.NAME, new OCId.Factory());
reflectionMap.put(NCPreview.NAME, new NCPreview.Factory());
reflectionMap.put(NCEncrypted.NAME, new NCEncrypted.Factory());
reflectionMap.put(OCFavorite.NAME, new OCFavorite.Factory());
reflectionMap.put(OCSize.NAME, new OCSize.Factory());
factories.set(propertyRegistry, reflectionMap);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
public static void registerCustomFactories() {
PropertyRegistry propertyRegistry = PropertyRegistry.INSTANCE;
try {
Field factories = propertyRegistry.getClass().getDeclaredField("factories");
factories.setAccessible(true);
Map<Property.Name, PropertyFactory> reflectionMap = (HashMap<Property.Name,
PropertyFactory>) factories.get(propertyRegistry);
reflectionMap.put(OCId.NAME, new OCId.Factory());
reflectionMap.put(NCPreview.NAME, new NCPreview.Factory());
reflectionMap.put(NCEncrypted.NAME, new NCEncrypted.Factory());
reflectionMap.put(OCFavorite.NAME, new OCFavorite.Factory());
reflectionMap.put(OCSize.NAME, new OCSize.Factory());
factories.set(propertyRegistry, reflectionMap);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}

View File

@ -37,63 +37,64 @@ import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
public class ReadFilesystemOperation {
private final OkHttpClient okHttpClient;
private final String url;
private final int depth;
private final String basePath;
private final OkHttpClient okHttpClient;
private final String url;
private final int depth;
private final String basePath;
public ReadFilesystemOperation(OkHttpClient okHttpClient, UserEntity currentUser, String path, int depth) {
OkHttpClient.Builder okHttpClientBuilder = okHttpClient.newBuilder();
okHttpClientBuilder.followRedirects(false);
okHttpClientBuilder.followSslRedirects(false);
okHttpClientBuilder.authenticator(new RestModule.MagicAuthenticator(ApiUtils.getCredentials(currentUser.getUsername(), currentUser.getToken()), "Authorization"));
this.okHttpClient = okHttpClientBuilder.build();
this.basePath = currentUser.getBaseUrl() + DavUtils.DAV_PATH + currentUser.getUserId();
this.url = basePath + path;
this.depth = depth;
public ReadFilesystemOperation(OkHttpClient okHttpClient, UserEntity currentUser, String path,
int depth) {
OkHttpClient.Builder okHttpClientBuilder = okHttpClient.newBuilder();
okHttpClientBuilder.followRedirects(false);
okHttpClientBuilder.followSslRedirects(false);
okHttpClientBuilder.authenticator(new RestModule.MagicAuthenticator(
ApiUtils.getCredentials(currentUser.getUsername(), currentUser.getToken()),
"Authorization"));
this.okHttpClient = okHttpClientBuilder.build();
this.basePath = currentUser.getBaseUrl() + DavUtils.DAV_PATH + currentUser.getUserId();
this.url = basePath + path;
this.depth = depth;
}
public DavResponse readRemotePath() {
DavResponse davResponse = new DavResponse();
final List<Response> memberElements = new ArrayList<>();
final Response[] rootElement = new Response[1];
final List<BrowserFile> remoteFiles = new ArrayList<>();
try {
new DavResource(okHttpClient, HttpUrl.parse(url)).propfind(depth, DavUtils.getAllPropSet(),
new Function2<Response, Response.HrefRelation, Unit>() {
@Override
public Unit invoke(Response response, Response.HrefRelation hrefRelation) {
davResponse.setResponse(response);
switch (hrefRelation) {
case MEMBER:
memberElements.add(response);
break;
case SELF:
rootElement[0] = response;
break;
case OTHER:
default:
}
return Unit.INSTANCE;
}
});
} catch (IOException e) {
e.printStackTrace();
} catch (DavException e) {
e.printStackTrace();
}
public DavResponse readRemotePath() {
DavResponse davResponse = new DavResponse();
final List<Response> memberElements = new ArrayList<>();
final Response[] rootElement = new Response[1];
final List<BrowserFile> remoteFiles = new ArrayList<>();
try {
new DavResource(okHttpClient, HttpUrl.parse(url)).propfind(depth, DavUtils.getAllPropSet(),
new Function2<Response, Response.HrefRelation, Unit>() {
@Override
public Unit invoke(Response response, Response.HrefRelation hrefRelation) {
davResponse.setResponse(response);
switch (hrefRelation) {
case MEMBER:
memberElements.add(response);
break;
case SELF:
rootElement[0] = response;
break;
case OTHER:
default:
}
return Unit.INSTANCE;
}
});
} catch (IOException e) {
e.printStackTrace();
} catch (DavException e) {
e.printStackTrace();
}
remoteFiles.add(BrowserFile.getModelFromResponse(rootElement[0],
rootElement[0].getHref().toString().substring(basePath.length())));
for (Response memberElement : memberElements) {
remoteFiles.add(BrowserFile.getModelFromResponse(memberElement,
memberElement.getHref().toString().substring(basePath.length())));
}
davResponse.setData(remoteFiles);
return davResponse;
remoteFiles.add(BrowserFile.getModelFromResponse(rootElement[0],
rootElement[0].getHref().toString().substring(basePath.length())));
for (Response memberElement : memberElements) {
remoteFiles.add(BrowserFile.getModelFromResponse(memberElement,
memberElement.getHref().toString().substring(basePath.length())));
}
davResponse.setData(remoteFiles);
return davResponse;
}
}

View File

@ -36,9 +36,6 @@ import autodagger.AutoInjector;
import butterknife.BindView;
import com.bluelinelabs.conductor.RouterTransaction;
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
import com.nextcloud.talk.models.json.conversations.RoomsOverall;
import com.nextcloud.talk.models.json.generic.Status;
import com.nextcloud.talk.models.json.userprofile.UserProfileOverall;
import com.nextcloud.talk.R;
import com.nextcloud.talk.api.NcApi;
import com.nextcloud.talk.application.NextcloudTalkApplication;
@ -48,6 +45,9 @@ import com.nextcloud.talk.jobs.CapabilitiesWorker;
import com.nextcloud.talk.jobs.PushRegistrationWorker;
import com.nextcloud.talk.jobs.SignalingSettingsWorker;
import com.nextcloud.talk.models.database.UserEntity;
import com.nextcloud.talk.models.json.conversations.RoomsOverall;
import com.nextcloud.talk.models.json.generic.Status;
import com.nextcloud.talk.models.json.userprofile.UserProfileOverall;
import com.nextcloud.talk.newarch.features.conversationsList.ConversationsListView;
import com.nextcloud.talk.utils.ApiUtils;
import com.nextcloud.talk.utils.ClosedInterfaceImpl;
@ -67,426 +67,435 @@ import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
@AutoInjector(NextcloudTalkApplication.class)
public class AccountVerificationController extends BaseController {
public static final String TAG = "AccountVerificationController";
public static final String TAG = "AccountVerificationController";
@Inject
NcApi ncApi;
@Inject
NcApi ncApi;
@Inject
UserUtils userUtils;
@Inject
UserUtils userUtils;
@Inject
CookieManager cookieManager;
@Inject
CookieManager cookieManager;
@Inject
AppPreferences appPreferences;
@Inject
AppPreferences appPreferences;
@Inject
EventBus eventBus;
@Inject
EventBus eventBus;
@BindView(R.id.progress_text)
TextView progressText;
@BindView(R.id.progress_text)
TextView progressText;
private long internalAccountId = -1;
private long internalAccountId = -1;
private String baseUrl;
private String username;
private String token;
private boolean isAccountImport;
private String originalProtocol;
private String baseUrl;
private String username;
private String token;
private boolean isAccountImport;
private String originalProtocol;
public AccountVerificationController(Bundle args) {
super();
if (args != null) {
baseUrl = args.getString(BundleKeys.INSTANCE.getKEY_BASE_URL());
username = args.getString(BundleKeys.INSTANCE.getKEY_USERNAME());
token = args.getString(BundleKeys.INSTANCE.getKEY_TOKEN());
if (args.containsKey(BundleKeys.INSTANCE.getKEY_IS_ACCOUNT_IMPORT())) {
isAccountImport = true;
}
if (args.containsKey(BundleKeys.INSTANCE.getKEY_ORIGINAL_PROTOCOL())) {
originalProtocol = args.getString(BundleKeys.INSTANCE.getKEY_ORIGINAL_PROTOCOL());
}
}
public AccountVerificationController(Bundle args) {
super();
if (args != null) {
baseUrl = args.getString(BundleKeys.INSTANCE.getKEY_BASE_URL());
username = args.getString(BundleKeys.INSTANCE.getKEY_USERNAME());
token = args.getString(BundleKeys.INSTANCE.getKEY_TOKEN());
if (args.containsKey(BundleKeys.INSTANCE.getKEY_IS_ACCOUNT_IMPORT())) {
isAccountImport = true;
}
if (args.containsKey(BundleKeys.INSTANCE.getKEY_ORIGINAL_PROTOCOL())) {
originalProtocol = args.getString(BundleKeys.INSTANCE.getKEY_ORIGINAL_PROTOCOL());
}
}
}
@Override
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
return inflater.inflate(R.layout.controller_account_verification, container, false);
}
@Override
protected void onDetach(@NonNull View view) {
eventBus.unregister(this);
super.onDetach(view);
}
@Override
protected void onAttach(@NonNull View view) {
super.onAttach(view);
eventBus.register(this);
}
@Override
protected void onViewBound(@NonNull View view) {
super.onViewBound(view);
NextcloudTalkApplication.Companion.getSharedApplication()
.getComponentApplication()
.inject(this);
if (getActivity() != null) {
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
@Override
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
return inflater.inflate(R.layout.controller_account_verification, container, false);
if (getActionBar() != null) {
getActionBar().hide();
}
@Override
protected void onDetach(@NonNull View view) {
eventBus.unregister(this);
super.onDetach(view);
if (isAccountImport && !baseUrl.startsWith("http://") && !baseUrl.startsWith("https://")
|| (!TextUtils
.isEmpty(originalProtocol) && !baseUrl.startsWith(originalProtocol))) {
determineBaseUrlProtocol(true);
} else {
checkEverything();
}
}
private void checkEverything() {
String credentials = ApiUtils.getCredentials(username, token);
cookieManager.getCookieStore().removeAll();
findServerTalkApp(credentials);
}
private void determineBaseUrlProtocol(boolean checkForcedHttps) {
cookieManager.getCookieStore().removeAll();
String queryUrl;
baseUrl = baseUrl.replace("http://", "").replace("https://", "");
if (checkForcedHttps) {
queryUrl = "https://" + baseUrl + ApiUtils.getUrlPostfixForStatus();
} else {
queryUrl = "http://" + baseUrl + ApiUtils.getUrlPostfixForStatus();
}
@Override
protected void onAttach(@NonNull View view) {
super.onAttach(view);
eventBus.register(this);
}
ncApi.getServerStatus(queryUrl)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.as(AutoDispose.autoDisposable(getScopeProvider()))
.subscribe(new Observer<Status>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
protected void onViewBound(@NonNull View view) {
super.onViewBound(view);
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
if (getActivity() != null) {
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
if (getActionBar() != null) {
getActionBar().hide();
}
if (isAccountImport && !baseUrl.startsWith("http://") && !baseUrl.startsWith("https://") || (!TextUtils
.isEmpty(originalProtocol) && !baseUrl.startsWith(originalProtocol))) {
determineBaseUrlProtocol(true);
} else {
checkEverything();
}
}
private void checkEverything() {
String credentials = ApiUtils.getCredentials(username, token);
cookieManager.getCookieStore().removeAll();
findServerTalkApp(credentials);
}
private void determineBaseUrlProtocol(boolean checkForcedHttps) {
cookieManager.getCookieStore().removeAll();
String queryUrl;
baseUrl = baseUrl.replace("http://", "").replace("https://", "");
if (checkForcedHttps) {
queryUrl = "https://" + baseUrl + ApiUtils.getUrlPostfixForStatus();
} else {
queryUrl = "http://" + baseUrl + ApiUtils.getUrlPostfixForStatus();
}
ncApi.getServerStatus(queryUrl)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.as(AutoDispose.autoDisposable(getScopeProvider()))
.subscribe(new Observer<Status>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Status status) {
if (checkForcedHttps) {
baseUrl = "https://" + baseUrl;
} else {
baseUrl = "http://" + baseUrl;
}
if (isAccountImport) {
getRouter().replaceTopController(RouterTransaction.with(new WebViewLoginController(baseUrl,
false, username, ""))
.pushChangeHandler(new HorizontalChangeHandler())
.popChangeHandler(new HorizontalChangeHandler()));
} else {
checkEverything();
}
}
@Override
public void onError(Throwable e) {
if (checkForcedHttps) {
determineBaseUrlProtocol(false);
} else {
abortVerification();
}
}
@Override
public void onComplete() {
}
});
}
private void findServerTalkApp(String credentials) {
ncApi.getRooms(credentials, ApiUtils.getUrlForGetRooms(baseUrl))
.subscribeOn(Schedulers.io())
.as(AutoDispose.autoDisposable(getScopeProvider()))
.subscribe(new Observer<RoomsOverall>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(RoomsOverall roomsOverall) {
fetchProfile(credentials);
}
@Override
public void onError(Throwable e) {
if (getActivity() != null && getResources() != null) {
getActivity().runOnUiThread(() -> progressText.setText(String.format(getResources().getString(
R.string.nc_nextcloud_talk_app_not_installed), getResources().getString(R.string.nc_app_name))));
}
ApplicationWideMessageHolder.getInstance().setMessageType(
ApplicationWideMessageHolder.MessageType.SERVER_WITHOUT_TALK);
abortVerification();
}
@Override
public void onComplete() {
}
});
}
private void storeProfile(String displayName, String userId) {
userUtils.createOrUpdateUser(username, token,
baseUrl, displayName, null, true,
userId, null, null,
appPreferences.getTemporaryClientCertAlias(), null)
.subscribeOn(Schedulers.io())
.as(AutoDispose.autoDisposable(getScopeProvider()))
.subscribe(new Observer<UserEntity>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(UserEntity userEntity) {
internalAccountId = userEntity.getId();
if (new ClosedInterfaceImpl().isGooglePlayServicesAvailable()) {
registerForPush();
} else {
getActivity().runOnUiThread(() -> progressText.setText(progressText.getText().toString() + "\n" +
getResources().getString(R.string.nc_push_disabled)));
fetchAndStoreCapabilities();
}
}
@Override
public void onError(Throwable e) {
progressText.setText(progressText.getText().toString() +
"\n" +
getResources().getString(
R.string.nc_display_name_not_stored));
abortVerification();
}
@Override
public void onComplete() {
}
});
}
private void fetchProfile(String credentials) {
ncApi.getUserProfile(credentials,
ApiUtils.getUrlForUserProfile(baseUrl))
.subscribeOn(Schedulers.io())
.as(AutoDispose.autoDisposable(getScopeProvider()))
.subscribe(new Observer<UserProfileOverall>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(UserProfileOverall userProfileOverall) {
String displayName = null;
if (!TextUtils.isEmpty(userProfileOverall.getOcs().getData()
.getDisplayName())) {
displayName = userProfileOverall.getOcs().getData()
.getDisplayName();
} else if (!TextUtils.isEmpty(userProfileOverall.getOcs().getData()
.getDisplayNameAlt())) {
displayName = userProfileOverall.getOcs().getData()
.getDisplayNameAlt();
}
if (!TextUtils.isEmpty(displayName)) {
storeProfile(displayName, userProfileOverall.getOcs().getData().getUserId());
} else {
if (getActivity() != null) {
getActivity().runOnUiThread(() -> progressText.setText(progressText.getText().toString() + "\n" +
getResources().getString(R.string.nc_display_name_not_fetched)));
}
abortVerification();
}
}
@Override
public void onError(Throwable e) {
if (getActivity() != null) {
getActivity().runOnUiThread(() -> progressText.setText(progressText.getText().toString() + "\n" +
getResources().getString(R.string.nc_display_name_not_fetched)));
}
abortVerification();
}
@Override
public void onComplete() {
}
});
}
private void registerForPush() {
OneTimeWorkRequest pushRegistrationWork = new OneTimeWorkRequest.Builder(PushRegistrationWorker.class).build();
WorkManager.getInstance().enqueue(pushRegistrationWork);
}
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onMessageEvent(EventStatus eventStatus) {
if (eventStatus.getEventType().equals(EventStatus.EventType.PUSH_REGISTRATION)) {
if (internalAccountId == eventStatus.getUserId() && !eventStatus.isAllGood() && getActivity() != null) {
getActivity().runOnUiThread(() -> progressText.setText(progressText.getText().toString() + "\n" +
getResources().getString(R.string.nc_push_disabled)));
}
fetchAndStoreCapabilities();
} else if (eventStatus.getEventType().equals(EventStatus.EventType.CAPABILITIES_FETCH)) {
if (internalAccountId == eventStatus.getUserId() && !eventStatus.isAllGood()) {
if (getActivity() != null) {
getActivity().runOnUiThread(() -> progressText.setText(progressText.getText().toString() + "\n" +
getResources().getString(R.string.nc_capabilities_failed)));
}
abortVerification();
} else if (internalAccountId == eventStatus.getUserId() && eventStatus.isAllGood()) {
fetchAndStoreExternalSignalingSettings();
}
} else if (eventStatus.getEventType().equals(EventStatus.EventType.SIGNALING_SETTINGS)) {
if (internalAccountId == eventStatus.getUserId() && !eventStatus.isAllGood()) {
if (getActivity() != null) {
getActivity().runOnUiThread(() -> progressText.setText(progressText.getText().toString() + "\n" +
getResources().getString(R.string.nc_external_server_failed)));
}
}
proceedWithLogin();
}
}
private void fetchAndStoreCapabilities() {
Data userData = new Data.Builder()
.putLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), internalAccountId)
.build();
OneTimeWorkRequest pushNotificationWork = new OneTimeWorkRequest.Builder(CapabilitiesWorker.class)
.setInputData(userData)
.build();
WorkManager.getInstance().enqueue(pushNotificationWork);
}
private void fetchAndStoreExternalSignalingSettings() {
Data userData = new Data.Builder()
.putLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), internalAccountId)
.build();
OneTimeWorkRequest signalingSettings = new OneTimeWorkRequest.Builder(SignalingSettingsWorker.class)
.setInputData(userData)
.build();
WorkManager.getInstance().enqueue(signalingSettings);
}
private void proceedWithLogin() {
cookieManager.getCookieStore().removeAll();
userUtils.disableAllUsersWithoutId(internalAccountId);
if (getActivity() != null) {
getActivity().runOnUiThread(() -> {
if (userUtils.getUsers().size() == 1) {
getRouter().setRoot(RouterTransaction.with(new
ConversationsListView())
.pushChangeHandler(new HorizontalChangeHandler())
.popChangeHandler(new HorizontalChangeHandler()));
} else {
if (isAccountImport) {
ApplicationWideMessageHolder.getInstance().setMessageType(
ApplicationWideMessageHolder.MessageType.ACCOUNT_WAS_IMPORTED);
}
getRouter().popToRoot();
}
});
}
}
@Override
protected void onDestroyView(@NonNull View view) {
super.onDestroyView(view);
if (getActivity() != null) {
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
}
}
private void abortVerification() {
if (!isAccountImport) {
if (internalAccountId != -1) {
userUtils.deleteUserWithId(internalAccountId).subscribe(new CompletableObserver() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onComplete() {
if (getActivity() != null) {
getActivity().runOnUiThread(() -> {
new Handler().postDelayed(() -> getRouter().popToRoot(), 7500);
});
}
}
@Override
public void onError(Throwable e) {
}
});
@Override
public void onNext(Status status) {
if (checkForcedHttps) {
baseUrl = "https://" + baseUrl;
} else {
if (getActivity() != null) {
getActivity().runOnUiThread(() -> {
new Handler().postDelayed(() -> getRouter().popToRoot(), 7500);
});
}
baseUrl = "http://" + baseUrl;
}
} else {
if (isAccountImport) {
getRouter().replaceTopController(
RouterTransaction.with(new WebViewLoginController(baseUrl,
false, username, ""))
.pushChangeHandler(new HorizontalChangeHandler())
.popChangeHandler(new HorizontalChangeHandler()));
} else {
checkEverything();
}
}
@Override
public void onError(Throwable e) {
if (checkForcedHttps) {
determineBaseUrlProtocol(false);
} else {
abortVerification();
}
}
@Override
public void onComplete() {
}
});
}
private void findServerTalkApp(String credentials) {
ncApi.getRooms(credentials, ApiUtils.getUrlForGetRooms(baseUrl))
.subscribeOn(Schedulers.io())
.as(AutoDispose.autoDisposable(getScopeProvider()))
.subscribe(new Observer<RoomsOverall>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(RoomsOverall roomsOverall) {
fetchProfile(credentials);
}
@Override
public void onError(Throwable e) {
if (getActivity() != null && getResources() != null) {
getActivity().runOnUiThread(
() -> progressText.setText(String.format(getResources().getString(
R.string.nc_nextcloud_talk_app_not_installed),
getResources().getString(R.string.nc_app_name))));
}
ApplicationWideMessageHolder.getInstance().setMessageType(
ApplicationWideMessageHolder.MessageType.FAILED_TO_IMPORT_ACCOUNT);
if (getActivity() != null) {
getActivity().runOnUiThread(() -> new Handler().postDelayed(() -> {
if (getRouter().hasRootController()) {
if (getActivity() != null) {
getRouter().popToRoot();
}
ApplicationWideMessageHolder.MessageType.SERVER_WITHOUT_TALK);
abortVerification();
}
} else {
if (userUtils.anyUserExists()) {
getRouter().setRoot(RouterTransaction.with(new ConversationsListView())
.pushChangeHandler(new HorizontalChangeHandler())
.popChangeHandler(new HorizontalChangeHandler()));
} else {
getRouter().setRoot(RouterTransaction.with(new ServerSelectionController())
.pushChangeHandler(new HorizontalChangeHandler())
.popChangeHandler(new HorizontalChangeHandler()));
}
}
}, 7500));
@Override
public void onComplete() {
}
});
}
private void storeProfile(String displayName, String userId) {
userUtils.createOrUpdateUser(username, token,
baseUrl, displayName, null, true,
userId, null, null,
appPreferences.getTemporaryClientCertAlias(), null)
.subscribeOn(Schedulers.io())
.as(AutoDispose.autoDisposable(getScopeProvider()))
.subscribe(new Observer<UserEntity>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(UserEntity userEntity) {
internalAccountId = userEntity.getId();
if (new ClosedInterfaceImpl().isGooglePlayServicesAvailable()) {
registerForPush();
} else {
getActivity().runOnUiThread(
() -> progressText.setText(progressText.getText().toString() + "\n" +
getResources().getString(R.string.nc_push_disabled)));
fetchAndStoreCapabilities();
}
}
}
}
@Override
public void onError(Throwable e) {
progressText.setText(progressText.getText().toString() +
"\n" +
getResources().getString(
R.string.nc_display_name_not_stored));
abortVerification();
}
@Override
public void onComplete() {
}
});
}
private void fetchProfile(String credentials) {
ncApi.getUserProfile(credentials,
ApiUtils.getUrlForUserProfile(baseUrl))
.subscribeOn(Schedulers.io())
.as(AutoDispose.autoDisposable(getScopeProvider()))
.subscribe(new Observer<UserProfileOverall>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(UserProfileOverall userProfileOverall) {
String displayName = null;
if (!TextUtils.isEmpty(userProfileOverall.getOcs().getData()
.getDisplayName())) {
displayName = userProfileOverall.getOcs().getData()
.getDisplayName();
} else if (!TextUtils.isEmpty(userProfileOverall.getOcs().getData()
.getDisplayNameAlt())) {
displayName = userProfileOverall.getOcs().getData()
.getDisplayNameAlt();
}
if (!TextUtils.isEmpty(displayName)) {
storeProfile(displayName, userProfileOverall.getOcs().getData().getUserId());
} else {
if (getActivity() != null) {
getActivity().runOnUiThread(
() -> progressText.setText(progressText.getText().toString() + "\n" +
getResources().getString(R.string.nc_display_name_not_fetched)));
}
abortVerification();
}
}
@Override
public void onError(Throwable e) {
if (getActivity() != null) {
getActivity().runOnUiThread(
() -> progressText.setText(progressText.getText().toString() + "\n" +
getResources().getString(R.string.nc_display_name_not_fetched)));
}
abortVerification();
}
@Override
public void onComplete() {
}
});
}
private void registerForPush() {
OneTimeWorkRequest pushRegistrationWork =
new OneTimeWorkRequest.Builder(PushRegistrationWorker.class).build();
WorkManager.getInstance().enqueue(pushRegistrationWork);
}
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onMessageEvent(EventStatus eventStatus) {
if (eventStatus.getEventType().equals(EventStatus.EventType.PUSH_REGISTRATION)) {
if (internalAccountId == eventStatus.getUserId()
&& !eventStatus.isAllGood()
&& getActivity() != null) {
getActivity().runOnUiThread(
() -> progressText.setText(progressText.getText().toString() + "\n" +
getResources().getString(R.string.nc_push_disabled)));
}
fetchAndStoreCapabilities();
} else if (eventStatus.getEventType().equals(EventStatus.EventType.CAPABILITIES_FETCH)) {
if (internalAccountId == eventStatus.getUserId() && !eventStatus.isAllGood()) {
if (getActivity() != null) {
getActivity().runOnUiThread(
() -> progressText.setText(progressText.getText().toString() + "\n" +
getResources().getString(R.string.nc_capabilities_failed)));
}
abortVerification();
} else if (internalAccountId == eventStatus.getUserId() && eventStatus.isAllGood()) {
fetchAndStoreExternalSignalingSettings();
}
} else if (eventStatus.getEventType().equals(EventStatus.EventType.SIGNALING_SETTINGS)) {
if (internalAccountId == eventStatus.getUserId() && !eventStatus.isAllGood()) {
if (getActivity() != null) {
getActivity().runOnUiThread(
() -> progressText.setText(progressText.getText().toString() + "\n" +
getResources().getString(R.string.nc_external_server_failed)));
}
}
proceedWithLogin();
}
}
private void fetchAndStoreCapabilities() {
Data userData = new Data.Builder()
.putLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), internalAccountId)
.build();
OneTimeWorkRequest pushNotificationWork =
new OneTimeWorkRequest.Builder(CapabilitiesWorker.class)
.setInputData(userData)
.build();
WorkManager.getInstance().enqueue(pushNotificationWork);
}
private void fetchAndStoreExternalSignalingSettings() {
Data userData = new Data.Builder()
.putLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), internalAccountId)
.build();
OneTimeWorkRequest signalingSettings =
new OneTimeWorkRequest.Builder(SignalingSettingsWorker.class)
.setInputData(userData)
.build();
WorkManager.getInstance().enqueue(signalingSettings);
}
private void proceedWithLogin() {
cookieManager.getCookieStore().removeAll();
userUtils.disableAllUsersWithoutId(internalAccountId);
if (getActivity() != null) {
getActivity().runOnUiThread(() -> {
if (userUtils.getUsers().size() == 1) {
getRouter().setRoot(RouterTransaction.with(new
ConversationsListView())
.pushChangeHandler(new HorizontalChangeHandler())
.popChangeHandler(new HorizontalChangeHandler()));
} else {
if (isAccountImport) {
ApplicationWideMessageHolder.getInstance().setMessageType(
ApplicationWideMessageHolder.MessageType.ACCOUNT_WAS_IMPORTED);
}
getRouter().popToRoot();
}
});
}
}
@Override
protected void onDestroyView(@NonNull View view) {
super.onDestroyView(view);
if (getActivity() != null) {
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
}
}
private void abortVerification() {
if (!isAccountImport) {
if (internalAccountId != -1) {
userUtils.deleteUserWithId(internalAccountId).subscribe(new CompletableObserver() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onComplete() {
if (getActivity() != null) {
getActivity().runOnUiThread(() -> {
new Handler().postDelayed(() -> getRouter().popToRoot(), 7500);
});
}
}
@Override
public void onError(Throwable e) {
}
});
} else {
if (getActivity() != null) {
getActivity().runOnUiThread(() -> {
new Handler().postDelayed(() -> getRouter().popToRoot(), 7500);
});
}
}
} else {
ApplicationWideMessageHolder.getInstance().setMessageType(
ApplicationWideMessageHolder.MessageType.FAILED_TO_IMPORT_ACCOUNT);
if (getActivity() != null) {
getActivity().runOnUiThread(() -> new Handler().postDelayed(() -> {
if (getRouter().hasRootController()) {
if (getActivity() != null) {
getRouter().popToRoot();
}
} else {
if (userUtils.anyUserExists()) {
getRouter().setRoot(RouterTransaction.with(new ConversationsListView())
.pushChangeHandler(new HorizontalChangeHandler())
.popChangeHandler(new HorizontalChangeHandler()));
} else {
getRouter().setRoot(RouterTransaction.with(new ServerSelectionController())
.pushChangeHandler(new HorizontalChangeHandler())
.popChangeHandler(new HorizontalChangeHandler()));
}
}
}, 7500));
}
}
}
}

View File

@ -61,17 +61,17 @@ import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber;
import com.facebook.imagepipeline.image.CloseableImage;
import com.facebook.imagepipeline.postprocessors.BlurPostProcessor;
import com.facebook.imagepipeline.request.ImageRequest;
import com.nextcloud.talk.models.RingtoneSettings;
import com.nextcloud.talk.models.json.conversations.Conversation;
import com.nextcloud.talk.models.json.conversations.RoomsOverall;
import com.nextcloud.talk.models.json.participants.Participant;
import com.nextcloud.talk.models.json.participants.ParticipantsOverall;
import com.nextcloud.talk.R;
import com.nextcloud.talk.api.NcApi;
import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.controllers.base.BaseController;
import com.nextcloud.talk.events.ConfigurationChangeEvent;
import com.nextcloud.talk.models.RingtoneSettings;
import com.nextcloud.talk.models.database.UserEntity;
import com.nextcloud.talk.models.json.conversations.Conversation;
import com.nextcloud.talk.models.json.conversations.RoomsOverall;
import com.nextcloud.talk.models.json.participants.Participant;
import com.nextcloud.talk.models.json.participants.ParticipantsOverall;
import com.nextcloud.talk.utils.ApiUtils;
import com.nextcloud.talk.utils.DisplayUtils;
import com.nextcloud.talk.utils.DoNotDisturbUtils;
@ -97,397 +97,411 @@ import org.parceler.Parcels;
@AutoInjector(NextcloudTalkApplication.class)
public class CallNotificationController extends BaseController {
private static final String TAG = "CallNotificationController";
private static final String TAG = "CallNotificationController";
@Inject
NcApi ncApi;
@Inject
NcApi ncApi;
@Inject
AppPreferences appPreferences;
@Inject
AppPreferences appPreferences;
@Inject
Cache cache;
@Inject
Cache cache;
@Inject
EventBus eventBus;
@Inject
EventBus eventBus;
@Inject
Context context;
@Inject
Context context;
@BindView(R.id.conversationNameTextView)
TextView conversationNameTextView;
@BindView(R.id.conversationNameTextView)
TextView conversationNameTextView;
@BindView(R.id.avatarImageView)
SimpleDraweeView avatarImageView;
@BindView(R.id.avatarImageView)
SimpleDraweeView avatarImageView;
@BindView(R.id.callAnswerVoiceOnlyView)
SimpleDraweeView callAnswerVoiceOnlyView;
@BindView(R.id.callAnswerVoiceOnlyView)
SimpleDraweeView callAnswerVoiceOnlyView;
@BindView(R.id.callAnswerCameraView)
SimpleDraweeView callAnswerCameraView;
@BindView(R.id.callAnswerCameraView)
SimpleDraweeView callAnswerCameraView;
@BindView(R.id.backgroundImageView)
ImageView backgroundImageView;
@BindView(R.id.backgroundImageView)
ImageView backgroundImageView;
@BindView(R.id.incomingTextRelativeLayout)
RelativeLayout incomingTextRelativeLayout;
@BindView(R.id.incomingTextRelativeLayout)
RelativeLayout incomingTextRelativeLayout;
private Bundle originalBundle;
private String roomId;
private UserEntity userBeingCalled;
private String credentials;
private Conversation currentConversation;
private MediaPlayer mediaPlayer;
private boolean leavingScreen = false;
private RenderScript renderScript;
private Vibrator vibrator;
private Handler handler;
private Bundle originalBundle;
private String roomId;
private UserEntity userBeingCalled;
private String credentials;
private Conversation currentConversation;
private MediaPlayer mediaPlayer;
private boolean leavingScreen = false;
private RenderScript renderScript;
private Vibrator vibrator;
private Handler handler;
public CallNotificationController(Bundle args) {
super();
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
public CallNotificationController(Bundle args) {
super();
NextcloudTalkApplication.Companion.getSharedApplication()
.getComponentApplication()
.inject(this);
this.roomId = args.getString(BundleKeys.INSTANCE.getKEY_ROOM_ID(), "");
this.currentConversation = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_ROOM()));
this.userBeingCalled = args.getParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY());
this.roomId = args.getString(BundleKeys.INSTANCE.getKEY_ROOM_ID(), "");
this.currentConversation =
Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_ROOM()));
this.userBeingCalled = args.getParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY());
this.originalBundle = args;
credentials = ApiUtils.getCredentials(userBeingCalled.getUsername(), userBeingCalled.getToken());
this.originalBundle = args;
credentials =
ApiUtils.getCredentials(userBeingCalled.getUsername(), userBeingCalled.getToken());
}
@Override
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
return inflater.inflate(R.layout.controller_call_notification, container, false);
}
@Override
protected void onDetach(@NonNull View view) {
eventBus.unregister(this);
super.onDetach(view);
}
@Override
protected void onAttach(@NonNull View view) {
super.onAttach(view);
eventBus.register(this);
}
private void showAnswerControls() {
callAnswerCameraView.setVisibility(View.VISIBLE);
callAnswerVoiceOnlyView.setVisibility(View.VISIBLE);
}
@OnClick(R.id.callControlHangupView)
void hangup() {
leavingScreen = true;
if (getActivity() != null) {
getActivity().finish();
}
}
@Override
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
return inflater.inflate(R.layout.controller_call_notification, container, false);
}
@OnClick(R.id.callAnswerCameraView)
void answerWithCamera() {
originalBundle.putBoolean(BundleKeys.INSTANCE.getKEY_CALL_VOICE_ONLY(), false);
proceedToCall();
}
@Override
protected void onDetach(@NonNull View view) {
eventBus.unregister(this);
super.onDetach(view);
}
@OnClick(R.id.callAnswerVoiceOnlyView)
void answerVoiceOnly() {
originalBundle.putBoolean(BundleKeys.INSTANCE.getKEY_CALL_VOICE_ONLY(), true);
proceedToCall();
}
@Override
protected void onAttach(@NonNull View view) {
super.onAttach(view);
eventBus.register(this);
}
private void proceedToCall() {
originalBundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(),
currentConversation.getToken());
private void showAnswerControls() {
callAnswerCameraView.setVisibility(View.VISIBLE);
callAnswerVoiceOnlyView.setVisibility(View.VISIBLE);
}
getRouter().replaceTopController(RouterTransaction.with(new CallController(originalBundle))
.popChangeHandler(new HorizontalChangeHandler())
.pushChangeHandler(new HorizontalChangeHandler()));
}
@OnClick(R.id.callControlHangupView)
void hangup() {
leavingScreen = true;
private void checkIfAnyParticipantsRemainInRoom() {
ncApi.getPeersForCall(credentials, ApiUtils.getUrlForParticipants(userBeingCalled.getBaseUrl(),
currentConversation.getToken()))
.subscribeOn(Schedulers.io())
.takeWhile(observable -> !leavingScreen)
.retry(3)
.as(AutoDispose.autoDisposable(getScopeProvider()))
.subscribe(new Observer<ParticipantsOverall>() {
@Override
public void onSubscribe(Disposable d) {
}
if (getActivity() != null) {
getActivity().finish();
}
}
@Override
public void onNext(ParticipantsOverall participantsOverall) {
boolean hasParticipantsInCall = false;
boolean inCallOnDifferentDevice = false;
List<Participant> participantList = participantsOverall.getOcs().getData();
for (Participant participant : participantList) {
if (participant.getParticipantFlags() != Participant.ParticipantFlags.NOT_IN_CALL) {
hasParticipantsInCall = true;
@OnClick(R.id.callAnswerCameraView)
void answerWithCamera() {
originalBundle.putBoolean(BundleKeys.INSTANCE.getKEY_CALL_VOICE_ONLY(), false);
proceedToCall();
}
@OnClick(R.id.callAnswerVoiceOnlyView)
void answerVoiceOnly() {
originalBundle.putBoolean(BundleKeys.INSTANCE.getKEY_CALL_VOICE_ONLY(), true);
proceedToCall();
}
private void proceedToCall() {
originalBundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), currentConversation.getToken());
getRouter().replaceTopController(RouterTransaction.with(new CallController(originalBundle))
.popChangeHandler(new HorizontalChangeHandler())
.pushChangeHandler(new HorizontalChangeHandler()));
}
private void checkIfAnyParticipantsRemainInRoom() {
ncApi.getPeersForCall(credentials, ApiUtils.getUrlForParticipants(userBeingCalled.getBaseUrl(),
currentConversation.getToken()))
.subscribeOn(Schedulers.io())
.takeWhile(observable -> !leavingScreen)
.retry(3)
.as(AutoDispose.autoDisposable(getScopeProvider()))
.subscribe(new Observer<ParticipantsOverall>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(ParticipantsOverall participantsOverall) {
boolean hasParticipantsInCall = false;
boolean inCallOnDifferentDevice = false;
List<Participant> participantList = participantsOverall.getOcs().getData();
for (Participant participant : participantList) {
if (participant.getParticipantFlags() != Participant.ParticipantFlags.NOT_IN_CALL) {
hasParticipantsInCall = true;
if (participant.getUserId().equals(userBeingCalled.getUserId())) {
inCallOnDifferentDevice = true;
break;
}
}
}
if (!hasParticipantsInCall || inCallOnDifferentDevice) {
if (getActivity() != null) {
getActivity().runOnUiThread(() -> hangup());
}
}
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
if (!leavingScreen) {
checkIfAnyParticipantsRemainInRoom();
}
}
});
}
private void handleFromNotification() {
ncApi.getRooms(credentials, ApiUtils.getUrlForGetRooms(userBeingCalled.getBaseUrl()))
.subscribeOn(Schedulers.io())
.retry(3)
.observeOn(AndroidSchedulers.mainThread())
.as(AutoDispose.autoDisposable(getScopeProvider()))
.subscribe(new Observer<RoomsOverall>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(RoomsOverall roomsOverall) {
for (Conversation conversation : roomsOverall.getOcs().getData()) {
if (roomId.equals(conversation.getRoomId())) {
currentConversation = conversation;
runAllThings();
break;
}
}
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
private void runAllThings() {
if (conversationNameTextView != null) {
conversationNameTextView.setText(currentConversation.getDisplayName());
}
loadAvatar();
checkIfAnyParticipantsRemainInRoom();
showAnswerControls();
}
@SuppressLint("LongLogTag")
@Override
protected void onViewBound(@NonNull View view) {
super.onViewBound(view);
renderScript = RenderScript.create(getActivity());
if (handler == null) {
handler = new Handler();
try {
cache.evictAll();
} catch (IOException e) {
Log.e(TAG, "Failed to evict cache");
if (participant.getUserId().equals(userBeingCalled.getUserId())) {
inCallOnDifferentDevice = true;
break;
}
}
}
}
if (currentConversation == null) {
handleFromNotification();
if (!hasParticipantsInCall || inCallOnDifferentDevice) {
if (getActivity() != null) {
getActivity().runOnUiThread(() -> hangup());
}
}
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
if (!leavingScreen) {
checkIfAnyParticipantsRemainInRoom();
}
}
});
}
private void handleFromNotification() {
ncApi.getRooms(credentials, ApiUtils.getUrlForGetRooms(userBeingCalled.getBaseUrl()))
.subscribeOn(Schedulers.io())
.retry(3)
.observeOn(AndroidSchedulers.mainThread())
.as(AutoDispose.autoDisposable(getScopeProvider()))
.subscribe(new Observer<RoomsOverall>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(RoomsOverall roomsOverall) {
for (Conversation conversation : roomsOverall.getOcs().getData()) {
if (roomId.equals(conversation.getRoomId())) {
currentConversation = conversation;
runAllThings();
break;
}
}
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
private void runAllThings() {
if (conversationNameTextView != null) {
conversationNameTextView.setText(currentConversation.getDisplayName());
}
loadAvatar();
checkIfAnyParticipantsRemainInRoom();
showAnswerControls();
}
@SuppressLint("LongLogTag")
@Override
protected void onViewBound(@NonNull View view) {
super.onViewBound(view);
renderScript = RenderScript.create(getActivity());
if (handler == null) {
handler = new Handler();
try {
cache.evictAll();
} catch (IOException e) {
Log.e(TAG, "Failed to evict cache");
}
}
if (currentConversation == null) {
handleFromNotification();
} else {
runAllThings();
}
if (DoNotDisturbUtils.INSTANCE.shouldPlaySound()) {
String callRingtonePreferenceString = appPreferences.getCallRingtoneUri();
Uri ringtoneUri;
if (TextUtils.isEmpty(callRingtonePreferenceString)) {
// play default sound
ringtoneUri = Uri.parse("android.resource://" + getApplicationContext().getPackageName() +
"/raw/librem_by_feandesign_call");
} else {
try {
RingtoneSettings ringtoneSettings =
LoganSquare.parse(callRingtonePreferenceString, RingtoneSettings.class);
ringtoneUri = ringtoneSettings.getRingtoneUri();
} catch (IOException e) {
Log.e(TAG, "Failed to parse ringtone settings");
ringtoneUri = Uri.parse("android.resource://" + getApplicationContext().getPackageName() +
"/raw/librem_by_feandesign_call");
}
}
if (ringtoneUri != null && getActivity() != null) {
mediaPlayer = new MediaPlayer();
try {
mediaPlayer.setDataSource(getActivity(), ringtoneUri);
mediaPlayer.setLooping(true);
AudioAttributes audioAttributes =
new AudioAttributes.Builder().setContentType(AudioAttributes
.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
.build();
mediaPlayer.setAudioAttributes(audioAttributes);
mediaPlayer.setOnPreparedListener(mp -> mediaPlayer.start());
mediaPlayer.prepareAsync();
} catch (IOException e) {
Log.e(TAG, "Failed to set data source");
}
}
}
if (DoNotDisturbUtils.INSTANCE.shouldVibrate(appPreferences.getShouldVibrateSetting())) {
vibrator = (Vibrator) getApplicationContext().getSystemService(Context.VIBRATOR_SERVICE);
if (vibrator != null) {
long[] vibratePattern = new long[] { 0, 400, 800, 600, 800, 800, 800, 1000 };
int[] amplitudes = new int[] { 0, 255, 0, 255, 0, 255, 0, 255 };
VibrationEffect vibrationEffect;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (vibrator.hasAmplitudeControl()) {
vibrationEffect = VibrationEffect.createWaveform(vibratePattern, amplitudes, -1);
vibrator.vibrate(vibrationEffect);
} else {
vibrationEffect = VibrationEffect.createWaveform(vibratePattern, -1);
vibrator.vibrate(vibrationEffect);
}
} else {
runAllThings();
}
if (DoNotDisturbUtils.INSTANCE.shouldPlaySound()) {
String callRingtonePreferenceString = appPreferences.getCallRingtoneUri();
Uri ringtoneUri;
if (TextUtils.isEmpty(callRingtonePreferenceString)) {
// play default sound
ringtoneUri = Uri.parse("android.resource://" + getApplicationContext().getPackageName() +
"/raw/librem_by_feandesign_call");
} else {
try {
RingtoneSettings ringtoneSettings = LoganSquare.parse(callRingtonePreferenceString, RingtoneSettings.class);
ringtoneUri = ringtoneSettings.getRingtoneUri();
} catch (IOException e) {
Log.e(TAG, "Failed to parse ringtone settings");
ringtoneUri = Uri.parse("android.resource://" + getApplicationContext().getPackageName() +
"/raw/librem_by_feandesign_call");
}
}
if (ringtoneUri != null && getActivity() != null) {
mediaPlayer = new MediaPlayer();
try {
mediaPlayer.setDataSource(getActivity(), ringtoneUri);
mediaPlayer.setLooping(true);
AudioAttributes audioAttributes = new AudioAttributes.Builder().setContentType(AudioAttributes
.CONTENT_TYPE_SONIFICATION).setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE).build();
mediaPlayer.setAudioAttributes(audioAttributes);
mediaPlayer.setOnPreparedListener(mp -> mediaPlayer.start());
mediaPlayer.prepareAsync();
} catch (IOException e) {
Log.e(TAG, "Failed to set data source");
}
}
}
if (DoNotDisturbUtils.INSTANCE.shouldVibrate(appPreferences.getShouldVibrateSetting())) {
vibrator = (Vibrator) getApplicationContext().getSystemService(Context.VIBRATOR_SERVICE);
if (vibrator != null) {
long[] vibratePattern = new long[]{0, 400, 800, 600, 800, 800, 800, 1000};
int[] amplitudes = new int[]{0, 255, 0, 255, 0, 255, 0, 255};
VibrationEffect vibrationEffect;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (vibrator.hasAmplitudeControl()) {
vibrationEffect = VibrationEffect.createWaveform(vibratePattern, amplitudes, -1);
vibrator.vibrate(vibrationEffect);
} else {
vibrationEffect = VibrationEffect.createWaveform(vibratePattern, -1);
vibrator.vibrate(vibrationEffect);
}
} else {
vibrator.vibrate(vibratePattern, -1);
}
}
handler.postDelayed(() -> {
if (vibrator != null) {
vibrator.cancel();
}
}, 10000);
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(ConfigurationChangeEvent configurationChangeEvent) {
ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) avatarImageView.getLayoutParams();
int dimen = (int) getResources().getDimension(R.dimen.avatar_size_very_big);
layoutParams.width = dimen;
layoutParams.height = dimen;
avatarImageView.setLayoutParams(layoutParams);
}
private void loadAvatar() {
switch (currentConversation.getType()) {
case ROOM_TYPE_ONE_TO_ONE_CALL:
avatarImageView.setVisibility(View.VISIBLE);
ImageRequest imageRequest =
DisplayUtils.getImageRequestForUrl(ApiUtils.getUrlForAvatarWithName(userBeingCalled.getBaseUrl(),
currentConversation.getName(), R.dimen.avatar_size_very_big), null);
ImagePipeline imagePipeline = Fresco.getImagePipeline();
DataSource<CloseableReference<CloseableImage>> dataSource = imagePipeline.fetchDecodedImage(imageRequest, null);
dataSource.subscribe(new BaseBitmapDataSubscriber() {
@Override
protected void onNewResultImpl(@Nullable Bitmap bitmap) {
if (avatarImageView != null) {
avatarImageView.getHierarchy().setImage(new BitmapDrawable(bitmap), 100,
true);
if (getResources() != null) {
incomingTextRelativeLayout.setBackground(getResources().getDrawable(R.drawable
.incoming_gradient));
}
if ((AvatarStatusCodeHolder.getInstance().getStatusCode() == 200 || AvatarStatusCodeHolder.getInstance().getStatusCode() == 0) &&
userBeingCalled.hasSpreedFeatureCapability("no-ping")) {
if (getActivity() != null) {
Bitmap backgroundBitmap = bitmap.copy(bitmap.getConfig(), true);
new BlurPostProcessor(5, getActivity()).process(backgroundBitmap);
backgroundImageView.setImageDrawable(new BitmapDrawable(backgroundBitmap));
}
} else if (AvatarStatusCodeHolder.getInstance().getStatusCode() == 201) {
ColorArt colorArt = new ColorArt(bitmap);
int color = colorArt.getBackgroundColor();
float[] hsv = new float[3];
Color.colorToHSV(color, hsv);
hsv[2] *= 0.75f;
color = Color.HSVToColor(hsv);
backgroundImageView.setImageDrawable(new ColorDrawable(color));
}
}
}
@Override
protected void onFailureImpl(DataSource<CloseableReference<CloseableImage>> dataSource) {
}
}, UiThreadImmediateExecutorService.getInstance());
break;
case ROOM_GROUP_CALL:
avatarImageView.getHierarchy().setImage(DisplayUtils.getRoundedDrawable(context.getDrawable(R.drawable.ic_people_group_white_24px))
, 100, true);
case ROOM_PUBLIC_CALL:
avatarImageView.getHierarchy().setImage(DisplayUtils.getRoundedDrawable(context.getDrawable(R.drawable.ic_people_group_white_24px))
, 100, true);
break;
default:
}
}
private void endMediaAndVibratorNotifications() {
if (mediaPlayer != null) {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
mediaPlayer.release();
mediaPlayer = null;
vibrator.vibrate(vibratePattern, -1);
}
}
handler.postDelayed(() -> {
if (vibrator != null) {
vibrator.cancel();
vibrator.cancel();
}
}, 10000);
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(ConfigurationChangeEvent configurationChangeEvent) {
ConstraintLayout.LayoutParams layoutParams =
(ConstraintLayout.LayoutParams) avatarImageView.getLayoutParams();
int dimen = (int) getResources().getDimension(R.dimen.avatar_size_very_big);
layoutParams.width = dimen;
layoutParams.height = dimen;
avatarImageView.setLayoutParams(layoutParams);
}
private void loadAvatar() {
switch (currentConversation.getType()) {
case ROOM_TYPE_ONE_TO_ONE_CALL:
avatarImageView.setVisibility(View.VISIBLE);
ImageRequest imageRequest =
DisplayUtils.getImageRequestForUrl(
ApiUtils.getUrlForAvatarWithName(userBeingCalled.getBaseUrl(),
currentConversation.getName(), R.dimen.avatar_size_very_big), null);
ImagePipeline imagePipeline = Fresco.getImagePipeline();
DataSource<CloseableReference<CloseableImage>> dataSource =
imagePipeline.fetchDecodedImage(imageRequest, null);
dataSource.subscribe(new BaseBitmapDataSubscriber() {
@Override
protected void onNewResultImpl(@Nullable Bitmap bitmap) {
if (avatarImageView != null) {
avatarImageView.getHierarchy().setImage(new BitmapDrawable(bitmap), 100,
true);
if (getResources() != null) {
incomingTextRelativeLayout.setBackground(getResources().getDrawable(R.drawable
.incoming_gradient));
}
if ((AvatarStatusCodeHolder.getInstance().getStatusCode() == 200
|| AvatarStatusCodeHolder.getInstance().getStatusCode() == 0) &&
userBeingCalled.hasSpreedFeatureCapability("no-ping")) {
if (getActivity() != null) {
Bitmap backgroundBitmap = bitmap.copy(bitmap.getConfig(), true);
new BlurPostProcessor(5, getActivity()).process(backgroundBitmap);
backgroundImageView.setImageDrawable(new BitmapDrawable(backgroundBitmap));
}
} else if (AvatarStatusCodeHolder.getInstance().getStatusCode() == 201) {
ColorArt colorArt = new ColorArt(bitmap);
int color = colorArt.getBackgroundColor();
float[] hsv = new float[3];
Color.colorToHSV(color, hsv);
hsv[2] *= 0.75f;
color = Color.HSVToColor(hsv);
backgroundImageView.setImageDrawable(new ColorDrawable(color));
}
}
}
@Override
protected void onFailureImpl(DataSource<CloseableReference<CloseableImage>> dataSource) {
}
}, UiThreadImmediateExecutorService.getInstance());
break;
case ROOM_GROUP_CALL:
avatarImageView.getHierarchy()
.setImage(DisplayUtils.getRoundedDrawable(
context.getDrawable(R.drawable.ic_people_group_white_24px))
, 100, true);
case ROOM_PUBLIC_CALL:
avatarImageView.getHierarchy()
.setImage(DisplayUtils.getRoundedDrawable(
context.getDrawable(R.drawable.ic_people_group_white_24px))
, 100, true);
break;
default:
}
}
private void endMediaAndVibratorNotifications() {
if (mediaPlayer != null) {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
mediaPlayer.release();
mediaPlayer = null;
}
@Override
public void onDestroy() {
AvatarStatusCodeHolder.getInstance().setStatusCode(0);
leavingScreen = true;
if (handler != null) {
handler.removeCallbacksAndMessages(null);
handler = null;
}
endMediaAndVibratorNotifications();
super.onDestroy();
if (vibrator != null) {
vibrator.cancel();
}
}
@Override
public void onDestroy() {
AvatarStatusCodeHolder.getInstance().setStatusCode(0);
leavingScreen = true;
if (handler != null) {
handler.removeCallbacksAndMessages(null);
handler = null;
}
endMediaAndVibratorNotifications();
super.onDestroy();
}
}

View File

@ -48,122 +48,132 @@ import javax.inject.Inject;
@AutoInjector(NextcloudTalkApplication.class)
public class LockedController extends BaseController {
public static final String TAG = "LockedController";
private static final int REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS = 112;
public static final String TAG = "LockedController";
private static final int REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS = 112;
@Inject
AppPreferences appPreferences;
@Inject
AppPreferences appPreferences;
@Override
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
return inflater.inflate(R.layout.controller_locked, container, false);
@Override
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
return inflater.inflate(R.layout.controller_locked, container, false);
}
@Override
protected void onViewBound(@NonNull View view) {
super.onViewBound(view);
NextcloudTalkApplication.Companion.getSharedApplication()
.getComponentApplication()
.inject(this);
if (getActionBar() != null) {
getActionBar().hide();
}
}
@Override
protected void onViewBound(@NonNull View view) {
super.onViewBound(view);
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
if (getActionBar() != null) {
getActionBar().hide();
}
}
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
protected void onAttach(@NonNull View view) {
super.onAttach(view);
checkIfWeAreSecure();
}
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
protected void onAttach(@NonNull View view) {
super.onAttach(view);
checkIfWeAreSecure();
}
@RequiresApi(api = Build.VERSION_CODES.M)
@OnClick(R.id.unlockTextView)
void unlock() {
checkIfWeAreSecure();
}
@RequiresApi(api = Build.VERSION_CODES.M)
@OnClick(R.id.unlockTextView)
void unlock() {
checkIfWeAreSecure();
}
@RequiresApi(api = Build.VERSION_CODES.M)
private void showBiometricDialog() {
Context context = getActivity();
@RequiresApi(api = Build.VERSION_CODES.M)
private void showBiometricDialog() {
Context context = getActivity();
if (context != null) {
final BiometricPrompt.PromptInfo promptInfo = new BiometricPrompt.PromptInfo.Builder()
.setTitle(String.format(context.getString(R.string.nc_biometric_unlock),
context.getString(R.string.nc_app_name)))
.setNegativeButtonText(context.getString(R.string.nc_cancel))
.build();
if (context != null) {
final BiometricPrompt.PromptInfo promptInfo = new BiometricPrompt.PromptInfo.Builder()
.setTitle(String.format(context.getString(R.string.nc_biometric_unlock), context.getString(R.string.nc_app_name)))
.setNegativeButtonText(context.getString(R.string.nc_cancel))
.build();
Executor executor = Executors.newSingleThreadExecutor();
Executor executor = Executors.newSingleThreadExecutor();
final BiometricPrompt biometricPrompt = new BiometricPrompt((FragmentActivity) context, executor,
new BiometricPrompt.AuthenticationCallback() {
@Override
public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
super.onAuthenticationSucceeded(result);
Log.d(TAG, "Fingerprint recognised successfully");
new Handler(Looper.getMainLooper()).post(() -> getRouter().popCurrentController());
}
@Override
public void onAuthenticationFailed() {
super.onAuthenticationFailed();
Log.d(TAG, "Fingerprint not recognised");
}
@Override
public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
super.onAuthenticationError(errorCode, errString);
showAuthenticationScreen();
}
}
);
BiometricPrompt.CryptoObject cryptoObject = SecurityUtils.getCryptoObject();
if (cryptoObject != null) {
biometricPrompt.authenticate(promptInfo, cryptoObject);
} else {
biometricPrompt.authenticate(promptInfo);
}
}
}
@RequiresApi(api = Build.VERSION_CODES.M)
private void checkIfWeAreSecure() {
if (getActivity() != null) {
KeyguardManager keyguardManager = (KeyguardManager) getActivity().getSystemService(Context.KEYGUARD_SERVICE);
if (keyguardManager != null && keyguardManager.isKeyguardSecure() && appPreferences.getIsScreenLocked()) {
if (!SecurityUtils.checkIfWeAreAuthenticated(appPreferences.getScreenLockTimeout())) {
showBiometricDialog();
} else {
getRouter().popCurrentController();
final BiometricPrompt biometricPrompt =
new BiometricPrompt((FragmentActivity) context, executor,
new BiometricPrompt.AuthenticationCallback() {
@Override
public void onAuthenticationSucceeded(
@NonNull BiometricPrompt.AuthenticationResult result) {
super.onAuthenticationSucceeded(result);
Log.d(TAG, "Fingerprint recognised successfully");
new Handler(Looper.getMainLooper()).post(
() -> getRouter().popCurrentController());
}
}
}
}
private void showAuthenticationScreen() {
if (getActivity() != null) {
KeyguardManager keyguardManager = (KeyguardManager) getActivity().getSystemService(Context.KEYGUARD_SERVICE);
Intent intent = keyguardManager.createConfirmDeviceCredentialIntent(null, null);
if (intent != null) {
startActivityForResult(intent, REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS);
}
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS) {
if (resultCode == Activity.RESULT_OK) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (SecurityUtils.checkIfWeAreAuthenticated(appPreferences.getScreenLockTimeout())) {
Log.d(TAG, "All went well, dismiss locked controller");
getRouter().popCurrentController();
}
@Override
public void onAuthenticationFailed() {
super.onAuthenticationFailed();
Log.d(TAG, "Fingerprint not recognised");
}
} else {
Log.d(TAG, "Authorization failed");
}
}
@Override
public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
super.onAuthenticationError(errorCode, errString);
showAuthenticationScreen();
}
}
);
BiometricPrompt.CryptoObject cryptoObject = SecurityUtils.getCryptoObject();
if (cryptoObject != null) {
biometricPrompt.authenticate(promptInfo, cryptoObject);
} else {
biometricPrompt.authenticate(promptInfo);
}
}
}
@RequiresApi(api = Build.VERSION_CODES.M)
private void checkIfWeAreSecure() {
if (getActivity() != null) {
KeyguardManager keyguardManager =
(KeyguardManager) getActivity().getSystemService(Context.KEYGUARD_SERVICE);
if (keyguardManager != null
&& keyguardManager.isKeyguardSecure()
&& appPreferences.getIsScreenLocked()) {
if (!SecurityUtils.checkIfWeAreAuthenticated(appPreferences.getScreenLockTimeout())) {
showBiometricDialog();
} else {
getRouter().popCurrentController();
}
}
}
}
private void showAuthenticationScreen() {
if (getActivity() != null) {
KeyguardManager keyguardManager =
(KeyguardManager) getActivity().getSystemService(Context.KEYGUARD_SERVICE);
Intent intent = keyguardManager.createConfirmDeviceCredentialIntent(null, null);
if (intent != null) {
startActivityForResult(intent, REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS);
}
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS) {
if (resultCode == Activity.RESULT_OK) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (SecurityUtils.checkIfWeAreAuthenticated(appPreferences.getScreenLockTimeout())) {
Log.d(TAG, "All went well, dismiss locked controller");
getRouter().popCurrentController();
}
}
} else {
Log.d(TAG, "Authorization failed");
}
}
}
}

View File

@ -40,11 +40,11 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import autodagger.AutoInjector;
import butterknife.BindView;
import com.bluelinelabs.logansquare.LoganSquare;
import com.nextcloud.talk.models.RingtoneSettings;
import com.nextcloud.talk.R;
import com.nextcloud.talk.adapters.items.NotificationSoundItem;
import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.controllers.base.BaseController;
import com.nextcloud.talk.models.RingtoneSettings;
import com.nextcloud.talk.utils.bundle.BundleKeys;
import com.nextcloud.talk.utils.preferences.AppPreferences;
import eu.davidea.flexibleadapter.FlexibleAdapter;
@ -57,247 +57,255 @@ import java.util.List;
import javax.inject.Inject;
@AutoInjector(NextcloudTalkApplication.class)
public class RingtoneSelectionController extends BaseController implements FlexibleAdapter.OnItemClickListener {
public class RingtoneSelectionController extends BaseController
implements FlexibleAdapter.OnItemClickListener {
private static final String TAG = "RingtoneSelectionController";
private static final String TAG = "RingtoneSelectionController";
@BindView(R.id.recyclerView)
RecyclerView recyclerView;
@BindView(R.id.recyclerView)
RecyclerView recyclerView;
@BindView(R.id.swipe_refresh_layout)
SwipeRefreshLayout swipeRefreshLayout;
@BindView(R.id.swipe_refresh_layout)
SwipeRefreshLayout swipeRefreshLayout;
@Inject
AppPreferences appPreferences;
@Inject
AppPreferences appPreferences;
@Inject
Context context;
@Inject
Context context;
private FlexibleAdapter adapter;
private RecyclerView.AdapterDataObserver adapterDataObserver;
private List<AbstractFlexibleItem> abstractFlexibleItemList = new ArrayList<>();
private FlexibleAdapter adapter;
private RecyclerView.AdapterDataObserver adapterDataObserver;
private List<AbstractFlexibleItem> abstractFlexibleItemList = new ArrayList<>();
private boolean callNotificationSounds;
private MediaPlayer mediaPlayer;
private Handler cancelMediaPlayerHandler;
private boolean callNotificationSounds;
private MediaPlayer mediaPlayer;
private Handler cancelMediaPlayerHandler;
public RingtoneSelectionController(Bundle args) {
super();
setHasOptionsMenu(true);
this.callNotificationSounds = args.getBoolean(BundleKeys.INSTANCE.getKEY_ARE_CALL_SOUNDS(), false);
public RingtoneSelectionController(Bundle args) {
super();
setHasOptionsMenu(true);
this.callNotificationSounds =
args.getBoolean(BundleKeys.INSTANCE.getKEY_ARE_CALL_SOUNDS(), false);
}
@Override
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
return inflater.inflate(R.layout.controller_generic_rv, container, false);
}
@Override
protected void onViewBound(@NonNull View view) {
super.onViewBound(view);
NextcloudTalkApplication.Companion.getSharedApplication()
.getComponentApplication()
.inject(this);
if (adapter == null) {
adapter = new FlexibleAdapter<>(abstractFlexibleItemList, getActivity(), false);
adapter.setNotifyChangeOfUnfilteredItems(true)
.setMode(SelectableAdapter.Mode.SINGLE);
adapter.addListener(this);
cancelMediaPlayerHandler = new Handler();
}
@Override
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
return inflater.inflate(R.layout.controller_generic_rv, container, false);
adapter.addListener(this);
prepareViews();
fetchNotificationSounds();
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
return getRouter().popCurrentController();
default:
return super.onOptionsItemSelected(item);
}
}
private void prepareViews() {
RecyclerView.LayoutManager layoutManager = new SmoothScrollLinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);
recyclerView.setAdapter(adapter);
adapterDataObserver = new RecyclerView.AdapterDataObserver() {
@Override
public void onChanged() {
super.onChanged();
findSelectedSound();
}
};
adapter.registerAdapterDataObserver(adapterDataObserver);
swipeRefreshLayout.setEnabled(false);
}
@SuppressLint("LongLogTag")
private void findSelectedSound() {
boolean foundDefault = false;
String preferencesString = null;
if ((callNotificationSounds && TextUtils.isEmpty(
(preferencesString = appPreferences.getCallRingtoneUri())))
|| (!callNotificationSounds && TextUtils.isEmpty((preferencesString = appPreferences
.getMessageRingtoneUri())))) {
adapter.toggleSelection(1);
foundDefault = true;
}
@Override
protected void onViewBound(@NonNull View view) {
super.onViewBound(view);
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
if (adapter == null) {
adapter = new FlexibleAdapter<>(abstractFlexibleItemList, getActivity(), false);
adapter.setNotifyChangeOfUnfilteredItems(true)
.setMode(SelectableAdapter.Mode.SINGLE);
adapter.addListener(this);
cancelMediaPlayerHandler = new Handler();
}
adapter.addListener(this);
prepareViews();
fetchNotificationSounds();
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
return getRouter().popCurrentController();
default:
return super.onOptionsItemSelected(item);
}
}
private void prepareViews() {
RecyclerView.LayoutManager layoutManager = new SmoothScrollLinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);
recyclerView.setAdapter(adapter);
adapterDataObserver = new RecyclerView.AdapterDataObserver() {
@Override
public void onChanged() {
super.onChanged();
findSelectedSound();
}
};
adapter.registerAdapterDataObserver(adapterDataObserver);
swipeRefreshLayout.setEnabled(false);
}
@SuppressLint("LongLogTag")
private void findSelectedSound() {
boolean foundDefault = false;
String preferencesString = null;
if ((callNotificationSounds && TextUtils.isEmpty((preferencesString = appPreferences.getCallRingtoneUri())))
|| (!callNotificationSounds && TextUtils.isEmpty((preferencesString = appPreferences
.getMessageRingtoneUri())))) {
adapter.toggleSelection(1);
foundDefault = true;
}
if (!TextUtils.isEmpty(preferencesString) && !foundDefault) {
try {
RingtoneSettings ringtoneSettings = LoganSquare.parse(preferencesString, RingtoneSettings.class);
if (ringtoneSettings.getRingtoneUri() == null) {
adapter.toggleSelection(0);
} else if (ringtoneSettings.getRingtoneUri().toString().equals(getRingtoneString())) {
adapter.toggleSelection(1);
} else {
NotificationSoundItem notificationSoundItem;
for (int i = 2; i < adapter.getItemCount(); i++) {
notificationSoundItem = (NotificationSoundItem) adapter.getItem(i);
if (notificationSoundItem.getNotificationSoundUri().equals(ringtoneSettings.getRingtoneUri().toString())) {
adapter.toggleSelection(i);
break;
}
}
}
} catch (IOException e) {
Log.e(TAG, "Failed to parse ringtone settings");
}
}
adapter.unregisterAdapterDataObserver(adapterDataObserver);
adapterDataObserver = null;
}
private String getRingtoneString() {
if (callNotificationSounds) {
return ("android.resource://" + context.getPackageName() +
"/raw/librem_by_feandesign_call");
if (!TextUtils.isEmpty(preferencesString) && !foundDefault) {
try {
RingtoneSettings ringtoneSettings =
LoganSquare.parse(preferencesString, RingtoneSettings.class);
if (ringtoneSettings.getRingtoneUri() == null) {
adapter.toggleSelection(0);
} else if (ringtoneSettings.getRingtoneUri().toString().equals(getRingtoneString())) {
adapter.toggleSelection(1);
} else {
return ("android.resource://" + context.getPackageName() + "/raw" +
"/librem_by_feandesign_message");
}
}
private void fetchNotificationSounds() {
abstractFlexibleItemList.add(new NotificationSoundItem(getResources().getString(R.string.nc_settings_no_ringtone), null));
abstractFlexibleItemList.add(new NotificationSoundItem(getResources()
.getString(R.string.nc_settings_default_ringtone), getRingtoneString()));
if (getActivity() != null) {
RingtoneManager manager = new RingtoneManager(getActivity());
if (callNotificationSounds) {
manager.setType(RingtoneManager.TYPE_RINGTONE);
} else {
manager.setType(RingtoneManager.TYPE_NOTIFICATION);
}
Cursor cursor = manager.getCursor();
NotificationSoundItem notificationSoundItem;
while (cursor.moveToNext()) {
String notificationTitle = cursor.getString(RingtoneManager.TITLE_COLUMN_INDEX);
String notificationUri = cursor.getString(RingtoneManager.URI_COLUMN_INDEX);
String completeNotificationUri = notificationUri + "/" + cursor.getString(RingtoneManager
.ID_COLUMN_INDEX);
notificationSoundItem = new NotificationSoundItem(notificationTitle, completeNotificationUri);
abstractFlexibleItemList.add(notificationSoundItem);
NotificationSoundItem notificationSoundItem;
for (int i = 2; i < adapter.getItemCount(); i++) {
notificationSoundItem = (NotificationSoundItem) adapter.getItem(i);
if (notificationSoundItem.getNotificationSoundUri()
.equals(ringtoneSettings.getRingtoneUri().toString())) {
adapter.toggleSelection(i);
break;
}
}
}
adapter.updateDataSet(abstractFlexibleItemList, false);
} catch (IOException e) {
Log.e(TAG, "Failed to parse ringtone settings");
}
}
@Override
public String getTitle() {
return getResources().getString(R.string.nc_settings_notification_sounds);
adapter.unregisterAdapterDataObserver(adapterDataObserver);
adapterDataObserver = null;
}
private String getRingtoneString() {
if (callNotificationSounds) {
return ("android.resource://" + context.getPackageName() +
"/raw/librem_by_feandesign_call");
} else {
return ("android.resource://" + context.getPackageName() + "/raw" +
"/librem_by_feandesign_message");
}
}
private void fetchNotificationSounds() {
abstractFlexibleItemList.add(
new NotificationSoundItem(getResources().getString(R.string.nc_settings_no_ringtone),
null));
abstractFlexibleItemList.add(new NotificationSoundItem(getResources()
.getString(R.string.nc_settings_default_ringtone), getRingtoneString()));
if (getActivity() != null) {
RingtoneManager manager = new RingtoneManager(getActivity());
if (callNotificationSounds) {
manager.setType(RingtoneManager.TYPE_RINGTONE);
} else {
manager.setType(RingtoneManager.TYPE_NOTIFICATION);
}
Cursor cursor = manager.getCursor();
NotificationSoundItem notificationSoundItem;
while (cursor.moveToNext()) {
String notificationTitle = cursor.getString(RingtoneManager.TITLE_COLUMN_INDEX);
String notificationUri = cursor.getString(RingtoneManager.URI_COLUMN_INDEX);
String completeNotificationUri = notificationUri + "/" + cursor.getString(RingtoneManager
.ID_COLUMN_INDEX);
notificationSoundItem =
new NotificationSoundItem(notificationTitle, completeNotificationUri);
abstractFlexibleItemList.add(notificationSoundItem);
}
}
@SuppressLint("LongLogTag")
@Override
public boolean onItemClick(View view, int position) {
NotificationSoundItem notificationSoundItem = (NotificationSoundItem) adapter.getItem(position);
adapter.updateDataSet(abstractFlexibleItemList, false);
}
Uri ringtoneUri = null;
@Override
public String getTitle() {
return getResources().getString(R.string.nc_settings_notification_sounds);
}
if (!TextUtils.isEmpty(notificationSoundItem.getNotificationSoundUri())) {
ringtoneUri = Uri.parse(notificationSoundItem.getNotificationSoundUri());
@SuppressLint("LongLogTag")
@Override
public boolean onItemClick(View view, int position) {
NotificationSoundItem notificationSoundItem = (NotificationSoundItem) adapter.getItem(position);
endMediaPlayer();
mediaPlayer = MediaPlayer.create(getActivity(), ringtoneUri);
Uri ringtoneUri = null;
cancelMediaPlayerHandler = new Handler();
cancelMediaPlayerHandler.postDelayed(new Runnable() {
@Override
public void run() {
endMediaPlayer();
}
}, mediaPlayer.getDuration() + 25);
mediaPlayer.start();
if (!TextUtils.isEmpty(notificationSoundItem.getNotificationSoundUri())) {
ringtoneUri = Uri.parse(notificationSoundItem.getNotificationSoundUri());
endMediaPlayer();
mediaPlayer = MediaPlayer.create(getActivity(), ringtoneUri);
cancelMediaPlayerHandler = new Handler();
cancelMediaPlayerHandler.postDelayed(new Runnable() {
@Override
public void run() {
endMediaPlayer();
}
if (adapter.getSelectedPositions().size() == 0 || adapter.getSelectedPositions().get(0) != position) {
RingtoneSettings ringtoneSettings = new RingtoneSettings();
ringtoneSettings.setRingtoneName(notificationSoundItem.getNotificationSoundName());
ringtoneSettings.setRingtoneUri(ringtoneUri);
if (callNotificationSounds) {
try {
appPreferences.setCallRingtoneUri(LoganSquare.serialize(ringtoneSettings));
adapter.toggleSelection(position);
adapter.notifyDataSetChanged();
} catch (IOException e) {
Log.e(TAG, "Failed to store selected ringtone for calls");
}
} else {
try {
appPreferences.setMessageRingtoneUri(LoganSquare.serialize(ringtoneSettings));
adapter.toggleSelection(position);
adapter.notifyDataSetChanged();
} catch (IOException e) {
Log.e(TAG, "Failed to store selected ringtone for calls");
}
}
}
return true;
}, mediaPlayer.getDuration() + 25);
mediaPlayer.start();
}
private void endMediaPlayer() {
if (cancelMediaPlayerHandler != null) {
cancelMediaPlayerHandler.removeCallbacksAndMessages(null);
}
if (adapter.getSelectedPositions().size() == 0
|| adapter.getSelectedPositions().get(0) != position) {
RingtoneSettings ringtoneSettings = new RingtoneSettings();
ringtoneSettings.setRingtoneName(notificationSoundItem.getNotificationSoundName());
ringtoneSettings.setRingtoneUri(ringtoneUri);
if (mediaPlayer != null) {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
mediaPlayer.release();
mediaPlayer = null;
if (callNotificationSounds) {
try {
appPreferences.setCallRingtoneUri(LoganSquare.serialize(ringtoneSettings));
adapter.toggleSelection(position);
adapter.notifyDataSetChanged();
} catch (IOException e) {
Log.e(TAG, "Failed to store selected ringtone for calls");
}
} else {
try {
appPreferences.setMessageRingtoneUri(LoganSquare.serialize(ringtoneSettings));
adapter.toggleSelection(position);
adapter.notifyDataSetChanged();
} catch (IOException e) {
Log.e(TAG, "Failed to store selected ringtone for calls");
}
}
}
@Override
public void onDestroy() {
endMediaPlayer();
super.onDestroy();
return true;
}
private void endMediaPlayer() {
if (cancelMediaPlayerHandler != null) {
cancelMediaPlayerHandler.removeCallbacksAndMessages(null);
}
if (mediaPlayer != null) {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
mediaPlayer.release();
mediaPlayer = null;
}
}
@Override
public void onDestroy() {
endMediaPlayer();
super.onDestroy();
}
}

View File

@ -62,301 +62,309 @@ import studio.carbonylgroup.textfieldboxes.TextFieldBoxes;
@AutoInjector(NextcloudTalkApplication.class)
public class ServerSelectionController extends BaseController {
public static final String TAG = "ServerSelectionController";
public static final String TAG = "ServerSelectionController";
@BindView(R.id.extended_edit_text)
ExtendedEditText serverEntry;
@BindView(R.id.text_field_boxes)
TextFieldBoxes textFieldBoxes;
@BindView(R.id.progress_bar)
ProgressBar progressBar;
@BindView(R.id.helper_text_view)
TextView providersTextView;
@BindView(R.id.cert_text_view)
TextView certTextView;
@BindView(R.id.extended_edit_text)
ExtendedEditText serverEntry;
@BindView(R.id.text_field_boxes)
TextFieldBoxes textFieldBoxes;
@BindView(R.id.progress_bar)
ProgressBar progressBar;
@BindView(R.id.helper_text_view)
TextView providersTextView;
@BindView(R.id.cert_text_view)
TextView certTextView;
@Inject
NcApi ncApi;
@Inject
NcApi ncApi;
@Inject
UserUtils userUtils;
@Inject
UserUtils userUtils;
@Inject
AppPreferences appPreferences;
@Inject
AppPreferences appPreferences;
@Override
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
return inflater.inflate(R.layout.controller_server_selection, container, false);
}
@Override
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
return inflater.inflate(R.layout.controller_server_selection, container, false);
}
@SuppressLint("LongLogTag")
@OnClick(R.id.cert_text_view)
public void onCertClick() {
if (getActivity() != null) {
KeyChain.choosePrivateKeyAlias(getActivity(), alias -> {
if (alias != null) {
appPreferences.setTemporaryClientCertAlias(alias);
} else {
appPreferences.removeTemporaryClientCertAlias();
}
setCertTextView();
}, new String[]{"RSA", "EC"}, null, null, -1, null);
}
}
@Override
protected void onViewBound(@NonNull View view) {
super.onViewBound(view);
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
if (getActivity() != null) {
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
if (getActionBar() != null) {
getActionBar().hide();
}
textFieldBoxes.getEndIconImageButton().setBackgroundDrawable(getResources().getDrawable(R.drawable
.ic_arrow_forward_white_24px));
textFieldBoxes.getEndIconImageButton().setAlpha(0.5f);
textFieldBoxes.getEndIconImageButton().setEnabled(false);
textFieldBoxes.getEndIconImageButton().setVisibility(View.VISIBLE);
textFieldBoxes.getEndIconImageButton().setOnClickListener(view1 -> checkServerAndProceed());
if (TextUtils.isEmpty(getResources().getString(R.string.nc_providers_url)) && (TextUtils.isEmpty(getResources
().getString(R.string.nc_import_account_type)))) {
providersTextView.setVisibility(View.INVISIBLE);
@SuppressLint("LongLogTag")
@OnClick(R.id.cert_text_view)
public void onCertClick() {
if (getActivity() != null) {
KeyChain.choosePrivateKeyAlias(getActivity(), alias -> {
if (alias != null) {
appPreferences.setTemporaryClientCertAlias(alias);
} else {
if ((TextUtils.isEmpty(getResources
().getString(R.string.nc_import_account_type)) ||
AccountUtils.INSTANCE.findAccounts(userUtils.getUsers()).size() == 0) &&
userUtils.getUsers().size() == 0) {
providersTextView.setText(R.string.nc_get_from_provider);
providersTextView.setOnClickListener(view12 -> {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(getResources()
.getString(R.string.nc_providers_url)));
startActivity(browserIntent);
});
} else if (AccountUtils.INSTANCE.findAccounts(userUtils.getUsers()).size() > 0) {
if (!TextUtils.isEmpty(AccountUtils.INSTANCE.getAppNameBasedOnPackage(getResources()
.getString(R.string.nc_import_accounts_from)))) {
if (AccountUtils.INSTANCE.findAccounts(userUtils.getUsers()).size() > 1) {
providersTextView.setText(String.format(getResources().getString(R.string
.nc_server_import_accounts), AccountUtils.INSTANCE.getAppNameBasedOnPackage(getResources()
.getString(R.string.nc_import_accounts_from))));
} else {
providersTextView.setText(String.format(getResources().getString(R.string
.nc_server_import_account), AccountUtils.INSTANCE.getAppNameBasedOnPackage(getResources()
.getString(R.string.nc_import_accounts_from))));
}
} else {
if (AccountUtils.INSTANCE.findAccounts(userUtils.getUsers()).size() > 1) {
providersTextView.setText(getResources().getString(R.string.nc_server_import_accounts_plain));
} else {
providersTextView.setText(getResources().getString(R.string
.nc_server_import_account_plain));
}
}
providersTextView.setOnClickListener(view13 -> {
Bundle bundle = new Bundle();
bundle.putBoolean(BundleKeys.INSTANCE.getKEY_IS_ACCOUNT_IMPORT(), true);
getRouter().pushController(RouterTransaction.with(
new SwitchAccountController(bundle))
.pushChangeHandler(new HorizontalChangeHandler())
.popChangeHandler(new HorizontalChangeHandler()));
});
} else {
providersTextView.setVisibility(View.INVISIBLE);
}
}
serverEntry.requestFocus();
serverEntry.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
if (!textFieldBoxes.isOnError() && !TextUtils.isEmpty(serverEntry.getText())) {
toggleProceedButton(true);
} else {
toggleProceedButton(false);
}
}
});
serverEntry.setOnEditorActionListener((textView, i, keyEvent) -> {
if (i == EditorInfo.IME_ACTION_DONE) {
checkServerAndProceed();
}
return false;
});
}
private void toggleProceedButton(boolean show) {
textFieldBoxes.getEndIconImageButton().setEnabled(show);
if (show) {
textFieldBoxes.getEndIconImageButton().setAlpha(1f);
} else {
textFieldBoxes.getEndIconImageButton().setAlpha(0.5f);
}
}
private void checkServerAndProceed() {
String url = serverEntry.getText().toString().trim();
serverEntry.setEnabled(false);
progressBar.setVisibility(View.VISIBLE);
if (providersTextView.getVisibility() != View.INVISIBLE) {
providersTextView.setVisibility(View.INVISIBLE);
certTextView.setVisibility(View.INVISIBLE);
}
if (url.endsWith("/")) {
url = url.substring(0, url.length() - 1);
}
String queryUrl = url + ApiUtils.getUrlPostfixForStatus();
if (url.startsWith("http://") || url.startsWith("https://")) {
checkServer(queryUrl, false);
} else {
checkServer("https://" + queryUrl, true);
}
}
private void checkServer(String queryUrl, boolean checkForcedHttps) {
ncApi.getServerStatus(queryUrl)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.as(AutoDispose.autoDisposable(getScopeProvider()))
.subscribe(status -> {
String productName = getResources().getString(R.string.nc_server_product_name);
String versionString = status.getVersion().substring(0, status.getVersion().indexOf("."));
int version = Integer.parseInt(versionString);
if (status.isInstalled() && !status.isMaintenance() &&
!status.isNeedsUpgrade() &&
version >= 13) {
getRouter().pushController(RouterTransaction.with(
new WebViewLoginController(queryUrl.replace("/status.php", ""),
false))
.pushChangeHandler(new HorizontalChangeHandler())
.popChangeHandler(new HorizontalChangeHandler()));
} else if (!status.isInstalled()) {
textFieldBoxes.setError(String.format(
getResources().getString(R.string.nc_server_not_installed), productName),
true);
toggleProceedButton(false);
} else if (status.isNeedsUpgrade()) {
textFieldBoxes.setError(String.format(getResources().
getString(R.string.nc_server_db_upgrade_needed),
productName), true);
toggleProceedButton(false);
} else if (status.isMaintenance()) {
textFieldBoxes.setError(String.format(getResources().
getString(R.string.nc_server_maintenance),
productName),
true);
toggleProceedButton(false);
} else if (!status.getVersion().startsWith("13.")) {
textFieldBoxes.setError(String.format(getResources().
getString(R.string.nc_server_version),
getResources().getString(R.string.nc_app_name)
, productName), true);
toggleProceedButton(false);
}
}, throwable -> {
if (checkForcedHttps) {
checkServer(queryUrl.replace("https://", "http://"), false);
} else {
if (throwable.getLocalizedMessage() != null) {
textFieldBoxes.setError(throwable.getLocalizedMessage(), true);
} else if (throwable.getCause() instanceof CertificateException) {
textFieldBoxes.setError(getResources().getString(R.string.nc_certificate_error),
false);
}
if (serverEntry != null) {
serverEntry.setEnabled(true);
}
progressBar.setVisibility(View.INVISIBLE);
if (providersTextView.getVisibility() != View.INVISIBLE) {
providersTextView.setVisibility(View.VISIBLE);
certTextView.setVisibility(View.VISIBLE);
}
toggleProceedButton(false);
}
}, () -> {
progressBar.setVisibility(View.INVISIBLE);
if (providersTextView.getVisibility() != View.INVISIBLE) {
providersTextView.setVisibility(View.VISIBLE);
certTextView.setVisibility(View.VISIBLE);
}
});
}
@Override
protected void onAttach(@NonNull View view) {
super.onAttach(view);
if (ApplicationWideMessageHolder.getInstance().getMessageType() != null) {
if (ApplicationWideMessageHolder.getInstance().getMessageType()
.equals(ApplicationWideMessageHolder.MessageType.ACCOUNT_SCHEDULED_FOR_DELETION)) {
textFieldBoxes.setError(getResources().getString(R.string.nc_account_scheduled_for_deletion),
false);
ApplicationWideMessageHolder.getInstance().setMessageType(null);
} else if (ApplicationWideMessageHolder.getInstance().getMessageType()
.equals(ApplicationWideMessageHolder.MessageType.SERVER_WITHOUT_TALK)) {
textFieldBoxes.setError(getResources().getString(R.string.nc_settings_no_talk_installed),
false);
} else if (ApplicationWideMessageHolder.getInstance().getMessageType()
.equals(ApplicationWideMessageHolder.MessageType.FAILED_TO_IMPORT_ACCOUNT)) {
textFieldBoxes.setError(getResources().getString(R.string.nc_server_failed_to_import_account),
false);
}
ApplicationWideMessageHolder.getInstance().setMessageType(null);
appPreferences.removeTemporaryClientCertAlias();
}
setCertTextView();
}, new String[] { "RSA", "EC" }, null, null, -1, null);
}
}
@Override
protected void onViewBound(@NonNull View view) {
super.onViewBound(view);
NextcloudTalkApplication.Companion.getSharedApplication()
.getComponentApplication()
.inject(this);
if (getActivity() != null) {
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
private void setCertTextView() {
if (getActivity() != null) {
getActivity().runOnUiThread(() -> {
if (!TextUtils.isEmpty(appPreferences.getTemporaryClientCertAlias())) {
certTextView.setText(R.string.nc_change_cert_auth);
} else {
certTextView.setText(R.string.nc_configure_cert_auth);
}
if (getActionBar() != null) {
getActionBar().hide();
}
textFieldBoxes.setError("", true);
toggleProceedButton(true);
});
textFieldBoxes.getEndIconImageButton()
.setBackgroundDrawable(getResources().getDrawable(R.drawable
.ic_arrow_forward_white_24px));
textFieldBoxes.getEndIconImageButton().setAlpha(0.5f);
textFieldBoxes.getEndIconImageButton().setEnabled(false);
textFieldBoxes.getEndIconImageButton().setVisibility(View.VISIBLE);
textFieldBoxes.getEndIconImageButton().setOnClickListener(view1 -> checkServerAndProceed());
if (TextUtils.isEmpty(getResources().getString(R.string.nc_providers_url))
&& (TextUtils.isEmpty(getResources
().getString(R.string.nc_import_account_type)))) {
providersTextView.setVisibility(View.INVISIBLE);
} else {
if ((TextUtils.isEmpty(getResources
().getString(R.string.nc_import_account_type)) ||
AccountUtils.INSTANCE.findAccounts(userUtils.getUsers()).size() == 0) &&
userUtils.getUsers().size() == 0) {
providersTextView.setText(R.string.nc_get_from_provider);
providersTextView.setOnClickListener(view12 -> {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(getResources()
.getString(R.string.nc_providers_url)));
startActivity(browserIntent);
});
} else if (AccountUtils.INSTANCE.findAccounts(userUtils.getUsers()).size() > 0) {
if (!TextUtils.isEmpty(AccountUtils.INSTANCE.getAppNameBasedOnPackage(getResources()
.getString(R.string.nc_import_accounts_from)))) {
if (AccountUtils.INSTANCE.findAccounts(userUtils.getUsers()).size() > 1) {
providersTextView.setText(String.format(getResources().getString(R.string
.nc_server_import_accounts),
AccountUtils.INSTANCE.getAppNameBasedOnPackage(getResources()
.getString(R.string.nc_import_accounts_from))));
} else {
providersTextView.setText(String.format(getResources().getString(R.string
.nc_server_import_account),
AccountUtils.INSTANCE.getAppNameBasedOnPackage(getResources()
.getString(R.string.nc_import_accounts_from))));
}
} else {
if (AccountUtils.INSTANCE.findAccounts(userUtils.getUsers()).size() > 1) {
providersTextView.setText(
getResources().getString(R.string.nc_server_import_accounts_plain));
} else {
providersTextView.setText(getResources().getString(R.string
.nc_server_import_account_plain));
}
}
providersTextView.setOnClickListener(view13 -> {
Bundle bundle = new Bundle();
bundle.putBoolean(BundleKeys.INSTANCE.getKEY_IS_ACCOUNT_IMPORT(), true);
getRouter().pushController(RouterTransaction.with(
new SwitchAccountController(bundle))
.pushChangeHandler(new HorizontalChangeHandler())
.popChangeHandler(new HorizontalChangeHandler()));
});
} else {
providersTextView.setVisibility(View.INVISIBLE);
}
}
@Override
protected void onDestroyView(@NonNull View view) {
super.onDestroyView(view);
if (getActivity() != null) {
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
serverEntry.requestFocus();
serverEntry.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
if (!textFieldBoxes.isOnError() && !TextUtils.isEmpty(serverEntry.getText())) {
toggleProceedButton(true);
} else {
toggleProceedButton(false);
}
}
});
serverEntry.setOnEditorActionListener((textView, i, keyEvent) -> {
if (i == EditorInfo.IME_ACTION_DONE) {
checkServerAndProceed();
}
return false;
});
}
private void toggleProceedButton(boolean show) {
textFieldBoxes.getEndIconImageButton().setEnabled(show);
if (show) {
textFieldBoxes.getEndIconImageButton().setAlpha(1f);
} else {
textFieldBoxes.getEndIconImageButton().setAlpha(0.5f);
}
}
private void checkServerAndProceed() {
String url = serverEntry.getText().toString().trim();
serverEntry.setEnabled(false);
progressBar.setVisibility(View.VISIBLE);
if (providersTextView.getVisibility() != View.INVISIBLE) {
providersTextView.setVisibility(View.INVISIBLE);
certTextView.setVisibility(View.INVISIBLE);
}
if (url.endsWith("/")) {
url = url.substring(0, url.length() - 1);
}
String queryUrl = url + ApiUtils.getUrlPostfixForStatus();
if (url.startsWith("http://") || url.startsWith("https://")) {
checkServer(queryUrl, false);
} else {
checkServer("https://" + queryUrl, true);
}
}
private void checkServer(String queryUrl, boolean checkForcedHttps) {
ncApi.getServerStatus(queryUrl)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.as(AutoDispose.autoDisposable(getScopeProvider()))
.subscribe(status -> {
String productName = getResources().getString(R.string.nc_server_product_name);
String versionString = status.getVersion().substring(0, status.getVersion().indexOf("."));
int version = Integer.parseInt(versionString);
if (status.isInstalled() && !status.isMaintenance() &&
!status.isNeedsUpgrade() &&
version >= 13) {
getRouter().pushController(RouterTransaction.with(
new WebViewLoginController(queryUrl.replace("/status.php", ""),
false))
.pushChangeHandler(new HorizontalChangeHandler())
.popChangeHandler(new HorizontalChangeHandler()));
} else if (!status.isInstalled()) {
textFieldBoxes.setError(String.format(
getResources().getString(R.string.nc_server_not_installed), productName),
true);
toggleProceedButton(false);
} else if (status.isNeedsUpgrade()) {
textFieldBoxes.setError(String.format(getResources().
getString(R.string.nc_server_db_upgrade_needed),
productName), true);
toggleProceedButton(false);
} else if (status.isMaintenance()) {
textFieldBoxes.setError(String.format(getResources().
getString(R.string.nc_server_maintenance),
productName),
true);
toggleProceedButton(false);
} else if (!status.getVersion().startsWith("13.")) {
textFieldBoxes.setError(String.format(getResources().
getString(R.string.nc_server_version),
getResources().getString(R.string.nc_app_name)
, productName), true);
toggleProceedButton(false);
}
}, throwable -> {
if (checkForcedHttps) {
checkServer(queryUrl.replace("https://", "http://"), false);
} else {
if (throwable.getLocalizedMessage() != null) {
textFieldBoxes.setError(throwable.getLocalizedMessage(), true);
} else if (throwable.getCause() instanceof CertificateException) {
textFieldBoxes.setError(getResources().getString(R.string.nc_certificate_error),
false);
}
if (serverEntry != null) {
serverEntry.setEnabled(true);
}
progressBar.setVisibility(View.INVISIBLE);
if (providersTextView.getVisibility() != View.INVISIBLE) {
providersTextView.setVisibility(View.VISIBLE);
certTextView.setVisibility(View.VISIBLE);
}
toggleProceedButton(false);
}
}, () -> {
progressBar.setVisibility(View.INVISIBLE);
if (providersTextView.getVisibility() != View.INVISIBLE) {
providersTextView.setVisibility(View.VISIBLE);
certTextView.setVisibility(View.VISIBLE);
}
});
}
@Override
protected void onAttach(@NonNull View view) {
super.onAttach(view);
if (ApplicationWideMessageHolder.getInstance().getMessageType() != null) {
if (ApplicationWideMessageHolder.getInstance().getMessageType()
.equals(ApplicationWideMessageHolder.MessageType.ACCOUNT_SCHEDULED_FOR_DELETION)) {
textFieldBoxes.setError(
getResources().getString(R.string.nc_account_scheduled_for_deletion),
false);
ApplicationWideMessageHolder.getInstance().setMessageType(null);
} else if (ApplicationWideMessageHolder.getInstance().getMessageType()
.equals(ApplicationWideMessageHolder.MessageType.SERVER_WITHOUT_TALK)) {
textFieldBoxes.setError(getResources().getString(R.string.nc_settings_no_talk_installed),
false);
} else if (ApplicationWideMessageHolder.getInstance().getMessageType()
.equals(ApplicationWideMessageHolder.MessageType.FAILED_TO_IMPORT_ACCOUNT)) {
textFieldBoxes.setError(
getResources().getString(R.string.nc_server_failed_to_import_account),
false);
}
ApplicationWideMessageHolder.getInstance().setMessageType(null);
}
setCertTextView();
}
private void setCertTextView() {
if (getActivity() != null) {
getActivity().runOnUiThread(() -> {
if (!TextUtils.isEmpty(appPreferences.getTemporaryClientCertAlias())) {
certTextView.setText(R.string.nc_change_cert_auth);
} else {
certTextView.setText(R.string.nc_configure_cert_auth);
}
textFieldBoxes.setError("", true);
toggleProceedButton(true);
});
}
}
@Override
protected void onDestroyView(@NonNull View view) {
super.onDestroyView(view);
if (getActivity() != null) {
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
}
}
}

View File

@ -37,13 +37,13 @@ import autodagger.AutoInjector;
import butterknife.BindView;
import com.bluelinelabs.conductor.RouterTransaction;
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
import com.nextcloud.talk.models.ImportAccount;
import com.nextcloud.talk.models.json.participants.Participant;
import com.nextcloud.talk.R;
import com.nextcloud.talk.adapters.items.AdvancedUserItem;
import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.controllers.base.BaseController;
import com.nextcloud.talk.models.ImportAccount;
import com.nextcloud.talk.models.database.UserEntity;
import com.nextcloud.talk.models.json.participants.Participant;
import com.nextcloud.talk.utils.AccountUtils;
import com.nextcloud.talk.utils.bundle.BundleKeys;
import com.nextcloud.talk.utils.database.user.UserUtils;
@ -61,189 +61,191 @@ import javax.inject.Inject;
@AutoInjector(NextcloudTalkApplication.class)
public class SwitchAccountController extends BaseController {
@Inject
UserUtils userUtils;
@Inject
UserUtils userUtils;
@BindView(R.id.recyclerView)
RecyclerView recyclerView;
@BindView(R.id.recyclerView)
RecyclerView recyclerView;
@Inject
CookieManager cookieManager;
@Inject
CookieManager cookieManager;
@BindView(R.id.swipe_refresh_layout)
SwipeRefreshLayout swipeRefreshLayout;
private FlexibleAdapter<AbstractFlexibleItem> adapter;
private List<AbstractFlexibleItem> userItems = new ArrayList<>();
@BindView(R.id.swipe_refresh_layout)
SwipeRefreshLayout swipeRefreshLayout;
private FlexibleAdapter<AbstractFlexibleItem> adapter;
private List<AbstractFlexibleItem> userItems = new ArrayList<>();
private boolean isAccountImport = false;
private boolean isAccountImport = false;
private FlexibleAdapter.OnItemClickListener onImportItemClickListener = new FlexibleAdapter.OnItemClickListener() {
private FlexibleAdapter.OnItemClickListener onImportItemClickListener =
new FlexibleAdapter.OnItemClickListener() {
@Override
public boolean onItemClick(View view, int position) {
if (userItems.size() > position) {
Account account = ((AdvancedUserItem) userItems.get(position)).getAccount();
reauthorizeFromImport(account);
}
if (userItems.size() > position) {
Account account = ((AdvancedUserItem) userItems.get(position)).getAccount();
reauthorizeFromImport(account);
}
return true;
return true;
}
};
};
private FlexibleAdapter.OnItemClickListener onSwitchItemClickListener = new FlexibleAdapter.OnItemClickListener() {
private FlexibleAdapter.OnItemClickListener onSwitchItemClickListener =
new FlexibleAdapter.OnItemClickListener() {
@Override
public boolean onItemClick(View view, int position) {
if (userItems.size() > position) {
UserEntity userEntity = ((AdvancedUserItem) userItems.get(position)).getEntity();
userUtils.createOrUpdateUser(null,
null, null, null,
null, true, null, userEntity.getId(), null, null, null)
.as(AutoDispose.autoDisposable(getScopeProvider()))
.subscribe(new Observer<UserEntity>() {
@Override
public void onSubscribe(Disposable d) {
if (userItems.size() > position) {
UserEntity userEntity = ((AdvancedUserItem) userItems.get(position)).getEntity();
userUtils.createOrUpdateUser(null,
null, null, null,
null, true, null, userEntity.getId(), null, null, null)
.as(AutoDispose.autoDisposable(getScopeProvider()))
.subscribe(new Observer<UserEntity>() {
@Override
public void onSubscribe(Disposable d) {
}
}
@Override
public void onNext(UserEntity userEntity) {
cookieManager.getCookieStore().removeAll();
@Override
public void onNext(UserEntity userEntity) {
cookieManager.getCookieStore().removeAll();
userUtils.disableAllUsersWithoutId(userEntity.getId());
if (getActivity() != null) {
getActivity().runOnUiThread(() -> getRouter().popCurrentController());
}
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
return true;
}
};
public SwitchAccountController() {
setHasOptionsMenu(true);
}
public SwitchAccountController(Bundle args) {
super();
setHasOptionsMenu(true);
if (args.containsKey(BundleKeys.INSTANCE.getKEY_IS_ACCOUNT_IMPORT())) {
isAccountImport = true;
}
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
getRouter().popCurrentController();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
return inflater.inflate(R.layout.controller_generic_rv, container, false);
}
@Override
protected void onViewBound(@NonNull View view) {
super.onViewBound(view);
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
swipeRefreshLayout.setEnabled(false);
if (getActionBar() != null) {
getActionBar().show();
}
if (adapter == null) {
adapter = new FlexibleAdapter<>(userItems, getActivity(), false);
UserEntity userEntity;
Participant participant;
if (!isAccountImport) {
for (Object userEntityObject : userUtils.getUsers()) {
userEntity = (UserEntity) userEntityObject;
if (!userEntity.getCurrent()) {
participant = new Participant();
participant.setName(userEntity.getDisplayName());
String userId;
if (userEntity.getUserId() != null) {
userId = userEntity.getUserId();
} else {
userId = userEntity.getUsername();
}
participant.setUserId(userId);
userItems.add(new AdvancedUserItem(participant, userEntity, null));
userUtils.disableAllUsersWithoutId(userEntity.getId());
if (getActivity() != null) {
getActivity().runOnUiThread(() -> getRouter().popCurrentController());
}
}
}
adapter.addListener(onSwitchItemClickListener);
adapter.updateDataSet(userItems, false);
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
return true;
}
};
public SwitchAccountController() {
setHasOptionsMenu(true);
}
public SwitchAccountController(Bundle args) {
super();
setHasOptionsMenu(true);
if (args.containsKey(BundleKeys.INSTANCE.getKEY_IS_ACCOUNT_IMPORT())) {
isAccountImport = true;
}
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
getRouter().popCurrentController();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
return inflater.inflate(R.layout.controller_generic_rv, container, false);
}
@Override
protected void onViewBound(@NonNull View view) {
super.onViewBound(view);
NextcloudTalkApplication.Companion.getSharedApplication()
.getComponentApplication()
.inject(this);
swipeRefreshLayout.setEnabled(false);
if (getActionBar() != null) {
getActionBar().show();
}
if (adapter == null) {
adapter = new FlexibleAdapter<>(userItems, getActivity(), false);
UserEntity userEntity;
Participant participant;
if (!isAccountImport) {
for (Object userEntityObject : userUtils.getUsers()) {
userEntity = (UserEntity) userEntityObject;
if (!userEntity.getCurrent()) {
participant = new Participant();
participant.setName(userEntity.getDisplayName());
String userId;
if (userEntity.getUserId() != null) {
userId = userEntity.getUserId();
} else {
Account account;
ImportAccount importAccount;
for (Object accountObject : AccountUtils.INSTANCE.findAccounts(userUtils.getUsers())) {
account = (Account) accountObject;
importAccount = AccountUtils.INSTANCE.getInformationFromAccount(account);
participant = new Participant();
participant.setName(importAccount.getUsername());
participant.setUserId(importAccount.getUsername());
userEntity = new UserEntity();
userEntity.setBaseUrl(importAccount.getBaseUrl());
userItems.add(new AdvancedUserItem(participant, userEntity, account));
}
adapter.addListener(onImportItemClickListener);
adapter.updateDataSet(userItems, false);
userId = userEntity.getUsername();
}
participant.setUserId(userId);
userItems.add(new AdvancedUserItem(participant, userEntity, null));
}
}
prepareViews();
adapter.addListener(onSwitchItemClickListener);
adapter.updateDataSet(userItems, false);
} else {
Account account;
ImportAccount importAccount;
for (Object accountObject : AccountUtils.INSTANCE.findAccounts(userUtils.getUsers())) {
account = (Account) accountObject;
importAccount = AccountUtils.INSTANCE.getInformationFromAccount(account);
participant = new Participant();
participant.setName(importAccount.getUsername());
participant.setUserId(importAccount.getUsername());
userEntity = new UserEntity();
userEntity.setBaseUrl(importAccount.getBaseUrl());
userItems.add(new AdvancedUserItem(participant, userEntity, account));
}
adapter.addListener(onImportItemClickListener);
adapter.updateDataSet(userItems, false);
}
}
prepareViews();
}
private void prepareViews() {
LinearLayoutManager layoutManager = new SmoothScrollLinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);
recyclerView.setAdapter(adapter);
private void prepareViews() {
LinearLayoutManager layoutManager = new SmoothScrollLinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);
recyclerView.setAdapter(adapter);
swipeRefreshLayout.setEnabled(false);
}
swipeRefreshLayout.setEnabled(false);
}
private void reauthorizeFromImport(Account account) {
ImportAccount importAccount = AccountUtils.INSTANCE.getInformationFromAccount(account);
Bundle bundle = new Bundle();
bundle.putString(BundleKeys.INSTANCE.getKEY_BASE_URL(), importAccount.getBaseUrl());
bundle.putString(BundleKeys.INSTANCE.getKEY_USERNAME(), importAccount.getUsername());
bundle.putString(BundleKeys.INSTANCE.getKEY_TOKEN(), importAccount.getToken());
bundle.putBoolean(BundleKeys.INSTANCE.getKEY_IS_ACCOUNT_IMPORT(), true);
getRouter().pushController(RouterTransaction.with(new AccountVerificationController(bundle))
.pushChangeHandler(new HorizontalChangeHandler())
.popChangeHandler(new HorizontalChangeHandler()));
}
private void reauthorizeFromImport(Account account) {
ImportAccount importAccount = AccountUtils.INSTANCE.getInformationFromAccount(account);
Bundle bundle = new Bundle();
bundle.putString(BundleKeys.INSTANCE.getKEY_BASE_URL(), importAccount.getBaseUrl());
bundle.putString(BundleKeys.INSTANCE.getKEY_USERNAME(), importAccount.getUsername());
bundle.putString(BundleKeys.INSTANCE.getKEY_TOKEN(), importAccount.getToken());
bundle.putBoolean(BundleKeys.INSTANCE.getKEY_IS_ACCOUNT_IMPORT(), true);
getRouter().pushController(RouterTransaction.with(new AccountVerificationController(bundle))
.pushChangeHandler(new HorizontalChangeHandler())
.popChangeHandler(new HorizontalChangeHandler()));
}
@Override
public String getTitle() {
return getResources().getString(R.string.nc_select_an_account);
}
@Override
public String getTitle() {
return getResources().getString(R.string.nc_select_an_account);
}
}

View File

@ -50,12 +50,12 @@ import autodagger.AutoInjector;
import butterknife.BindView;
import com.bluelinelabs.conductor.RouterTransaction;
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
import com.nextcloud.talk.models.LoginData;
import com.nextcloud.talk.R;
import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.controllers.base.BaseController;
import com.nextcloud.talk.events.CertificateEvent;
import com.nextcloud.talk.jobs.PushRegistrationWorker;
import com.nextcloud.talk.models.LoginData;
import com.nextcloud.talk.models.database.UserEntity;
import com.nextcloud.talk.utils.bundle.BundleKeys;
import com.nextcloud.talk.utils.database.user.UserUtils;
@ -84,388 +84,400 @@ import org.greenrobot.eventbus.EventBus;
@AutoInjector(NextcloudTalkApplication.class)
public class WebViewLoginController extends BaseController {
public static final String TAG = "WebViewLoginController";
public static final String TAG = "WebViewLoginController";
private final String PROTOCOL_SUFFIX = "://";
private final String LOGIN_URL_DATA_KEY_VALUE_SEPARATOR = ":";
private final String PROTOCOL_SUFFIX = "://";
private final String LOGIN_URL_DATA_KEY_VALUE_SEPARATOR = ":";
@Inject
UserUtils userUtils;
@Inject
AppPreferences appPreferences;
@Inject
ReactiveEntityStore<Persistable> dataStore;
@Inject
MagicTrustManager magicTrustManager;
@Inject
EventBus eventBus;
@Inject
CookieManager cookieManager;
@Inject
UserUtils userUtils;
@Inject
AppPreferences appPreferences;
@Inject
ReactiveEntityStore<Persistable> dataStore;
@Inject
MagicTrustManager magicTrustManager;
@Inject
EventBus eventBus;
@Inject
CookieManager cookieManager;
@BindView(R.id.webview)
WebView webView;
@BindView(R.id.webview)
WebView webView;
@BindView(R.id.progress_bar)
ProgressBar progressBar;
@BindView(R.id.progress_bar)
ProgressBar progressBar;
private String assembledPrefix;
private String assembledPrefix;
private Disposable userQueryDisposable;
private Disposable userQueryDisposable;
private String baseUrl;
private boolean isPasswordUpdate;
private String baseUrl;
private boolean isPasswordUpdate;
private String username;
private String password;
private int loginStep = 0;
private String username;
private String password;
private int loginStep = 0;
private boolean automatedLoginAttempted = false;
private boolean automatedLoginAttempted = false;
private WebViewFidoBridge webViewFidoBridge;
private WebViewFidoBridge webViewFidoBridge;
public WebViewLoginController(String baseUrl, boolean isPasswordUpdate) {
this.baseUrl = baseUrl;
this.isPasswordUpdate = isPasswordUpdate;
}
public WebViewLoginController(String baseUrl, boolean isPasswordUpdate) {
this.baseUrl = baseUrl;
this.isPasswordUpdate = isPasswordUpdate;
public WebViewLoginController(String baseUrl, boolean isPasswordUpdate, String username,
String password) {
this.baseUrl = baseUrl;
this.isPasswordUpdate = isPasswordUpdate;
this.username = username;
this.password = password;
}
private String getWebLoginUserAgent() {
return Build.MANUFACTURER.substring(0, 1).toUpperCase(Locale.getDefault()) +
Build.MANUFACTURER.substring(1).toLowerCase(Locale.getDefault()) + " " + Build.MODEL + " ("
+ getResources().getString(R.string.nc_app_name) + ")";
}
@Override
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
return inflater.inflate(R.layout.controller_web_view_login, container, false);
}
@SuppressLint("SetJavaScriptEnabled")
@Override
protected void onViewBound(@NonNull View view) {
super.onViewBound(view);
NextcloudTalkApplication.Companion.getSharedApplication()
.getComponentApplication()
.inject(this);
if (getActivity() != null) {
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
public WebViewLoginController(String baseUrl, boolean isPasswordUpdate, String username, String password) {
this.baseUrl = baseUrl;
this.isPasswordUpdate = isPasswordUpdate;
this.username = username;
this.password = password;
if (getActionBar() != null) {
getActionBar().hide();
}
private String getWebLoginUserAgent() {
return Build.MANUFACTURER.substring(0, 1).toUpperCase(Locale.getDefault()) +
Build.MANUFACTURER.substring(1).toLowerCase(Locale.getDefault()) + " " + Build.MODEL + " ("
+ getResources().getString(R.string.nc_app_name) + ")";
}
assembledPrefix =
getResources().getString(R.string.nc_talk_login_scheme) + PROTOCOL_SUFFIX + "login/";
@Override
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
return inflater.inflate(R.layout.controller_web_view_login, container, false);
}
webView.getSettings().setAllowFileAccess(false);
webView.getSettings().setAllowFileAccessFromFileURLs(false);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(false);
webView.getSettings().setDomStorageEnabled(true);
webView.getSettings().setUserAgentString(getWebLoginUserAgent());
webView.getSettings().setSaveFormData(false);
webView.getSettings().setSavePassword(false);
webView.getSettings().setRenderPriority(WebSettings.RenderPriority.HIGH);
webView.clearCache(true);
webView.clearFormData();
webView.clearHistory();
WebView.clearClientCertPreferences(null);
@SuppressLint("SetJavaScriptEnabled")
@Override
protected void onViewBound(@NonNull View view) {
super.onViewBound(view);
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
webViewFidoBridge =
WebViewFidoBridge.createInstanceForWebView((AppCompatActivity) getActivity(), webView);
if (getActivity() != null) {
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
CookieSyncManager.createInstance(getActivity());
android.webkit.CookieManager.getInstance().removeAllCookies(null);
Map<String, String> headers = new HashMap<>();
headers.put("OCS-APIRequest", "true");
webView.setWebViewClient(new WebViewClient() {
private boolean basePageLoaded;
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
webViewFidoBridge.delegateShouldInterceptRequest(view, request);
return super.shouldInterceptRequest(view, request);
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
webViewFidoBridge.delegateOnPageStarted(view, url, favicon);
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith(assembledPrefix)) {
parseAndLoginFromWebView(url);
return true;
}
return false;
}
@Override
public void onPageFinished(WebView view, String url) {
loginStep++;
if (!basePageLoaded) {
if (progressBar != null) {
progressBar.setVisibility(View.GONE);
}
if (webView != null) {
webView.setVisibility(View.VISIBLE);
}
basePageLoaded = true;
}
if (getActionBar() != null) {
getActionBar().hide();
}
assembledPrefix = getResources().getString(R.string.nc_talk_login_scheme) + PROTOCOL_SUFFIX + "login/";
webView.getSettings().setAllowFileAccess(false);
webView.getSettings().setAllowFileAccessFromFileURLs(false);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(false);
webView.getSettings().setDomStorageEnabled(true);
webView.getSettings().setUserAgentString(getWebLoginUserAgent());
webView.getSettings().setSaveFormData(false);
webView.getSettings().setSavePassword(false);
webView.getSettings().setRenderPriority(WebSettings.RenderPriority.HIGH);
webView.clearCache(true);
webView.clearFormData();
webView.clearHistory();
WebView.clearClientCertPreferences(null);
webViewFidoBridge = WebViewFidoBridge.createInstanceForWebView((AppCompatActivity) getActivity(), webView);
CookieSyncManager.createInstance(getActivity());
android.webkit.CookieManager.getInstance().removeAllCookies(null);
Map<String, String> headers = new HashMap<>();
headers.put("OCS-APIRequest", "true");
webView.setWebViewClient(new WebViewClient() {
private boolean basePageLoaded;
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
webViewFidoBridge.delegateShouldInterceptRequest(view, request);
return super.shouldInterceptRequest(view, request);
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
webViewFidoBridge.delegateOnPageStarted(view, url, favicon);
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith(assembledPrefix)) {
parseAndLoginFromWebView(url);
return true;
}
return false;
}
@Override
public void onPageFinished(WebView view, String url) {
loginStep++;
if (!basePageLoaded) {
if (progressBar != null) {
progressBar.setVisibility(View.GONE);
}
if (webView != null) {
webView.setVisibility(View.VISIBLE);
}
basePageLoaded = true;
}
if (!TextUtils.isEmpty(username) && webView != null) {
if (loginStep == 1) {
webView.loadUrl("javascript: {document.getElementsByClassName('login')[0].click(); };");
} else if (!automatedLoginAttempted) {
automatedLoginAttempted = true;
if (TextUtils.isEmpty(password)) {
webView.loadUrl("javascript:var justStore = document.getElementById('user').value = '" + username + "';");
} else {
webView.loadUrl("javascript: {" +
"document.getElementById('user').value = '" + username + "';" +
"document.getElementById('password').value = '" + password + "';" +
"document.getElementById('submit').click(); };");
}
}
}
super.onPageFinished(view, url);
}
@Override
public void onReceivedClientCertRequest(WebView view, ClientCertRequest request) {
UserEntity userEntity = userUtils.getCurrentUser();
String alias = null;
if (!isPasswordUpdate) {
alias = appPreferences.getTemporaryClientCertAlias();
}
if (TextUtils.isEmpty(alias) && (userEntity != null)) {
alias = userEntity.getClientCertificate();
}
if (!TextUtils.isEmpty(alias)) {
String finalAlias = alias;
new Thread(() -> {
try {
PrivateKey privateKey = KeyChain.getPrivateKey(getActivity(), finalAlias);
X509Certificate[] certificates = KeyChain.getCertificateChain(getActivity(), finalAlias);
if (privateKey != null && certificates != null) {
request.proceed(privateKey, certificates);
} else {
request.cancel();
}
} catch (KeyChainException | InterruptedException e) {
request.cancel();
}
}).start();
} else {
KeyChain.choosePrivateKeyAlias(getActivity(), chosenAlias -> {
if (chosenAlias != null) {
appPreferences.setTemporaryClientCertAlias(chosenAlias);
new Thread(() -> {
PrivateKey privateKey = null;
try {
privateKey = KeyChain.getPrivateKey(getActivity(), chosenAlias);
X509Certificate[] certificates = KeyChain.getCertificateChain(getActivity(), chosenAlias);
if (privateKey != null && certificates != null) {
request.proceed(privateKey, certificates);
} else {
request.cancel();
}
} catch (KeyChainException | InterruptedException e) {
request.cancel();
}
}).start();
} else {
request.cancel();
}
}, new String[]{"RSA", "EC"}, null, request.getHost(), request.getPort(), null);
}
}
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
try {
SslCertificate sslCertificate = error.getCertificate();
Field f = sslCertificate.getClass().getDeclaredField("mX509Certificate");
f.setAccessible(true);
X509Certificate cert = (X509Certificate) f.get(sslCertificate);
if (cert == null) {
handler.cancel();
} else {
try {
magicTrustManager.checkServerTrusted(new X509Certificate[]{cert}, "generic");
handler.proceed();
} catch (CertificateException exception) {
eventBus.post(new CertificateEvent(cert, magicTrustManager, handler));
}
}
} catch (Exception exception) {
handler.cancel();
}
}
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
}
});
webView.loadUrl(baseUrl + "/index.php/login/flow", headers);
}
private void dispose() {
if (userQueryDisposable != null && !userQueryDisposable.isDisposed()) {
userQueryDisposable.dispose();
}
userQueryDisposable = null;
}
private void parseAndLoginFromWebView(String dataString) {
LoginData loginData = parseLoginData(assembledPrefix, dataString);
if (loginData != null) {
dispose();
UserEntity currentUser = userUtils.getCurrentUser();
ApplicationWideMessageHolder.MessageType messageType = null;
if (!isPasswordUpdate && userUtils.getIfUserWithUsernameAndServer(loginData.getUsername(), baseUrl)) {
messageType = ApplicationWideMessageHolder.MessageType.ACCOUNT_UPDATED_NOT_ADDED;
}
if (userUtils.checkIfUserIsScheduledForDeletion(loginData.getUsername(), baseUrl)) {
ApplicationWideMessageHolder.getInstance().setMessageType(
ApplicationWideMessageHolder.MessageType.ACCOUNT_SCHEDULED_FOR_DELETION);
if (!isPasswordUpdate) {
getRouter().popToRoot();
} else {
getRouter().popCurrentController();
}
}
ApplicationWideMessageHolder.MessageType finalMessageType = messageType;
cookieManager.getCookieStore().removeAll();
if (!isPasswordUpdate && finalMessageType == null) {
Bundle bundle = new Bundle();
bundle.putString(BundleKeys.INSTANCE.getKEY_USERNAME(), loginData.getUsername());
bundle.putString(BundleKeys.INSTANCE.getKEY_TOKEN(), loginData.getToken());
bundle.putString(BundleKeys.INSTANCE.getKEY_BASE_URL(), loginData.getServerUrl());
String protocol = "";
if (baseUrl.startsWith("http://")) {
protocol = "http://";
} else if (baseUrl.startsWith("https://")) {
protocol = "https://";
}
if (!TextUtils.isEmpty(protocol)) {
bundle.putString(BundleKeys.INSTANCE.getKEY_ORIGINAL_PROTOCOL(), protocol);
}
getRouter().pushController(RouterTransaction.with(new AccountVerificationController
(bundle)).pushChangeHandler(new HorizontalChangeHandler())
.popChangeHandler(new HorizontalChangeHandler()));
if (!TextUtils.isEmpty(username) && webView != null) {
if (loginStep == 1) {
webView.loadUrl("javascript: {document.getElementsByClassName('login')[0].click(); };");
} else if (!automatedLoginAttempted) {
automatedLoginAttempted = true;
if (TextUtils.isEmpty(password)) {
webView.loadUrl("javascript:var justStore = document.getElementById('user').value = '"
+ username
+ "';");
} else {
if (isPasswordUpdate) {
if (currentUser != null) {
userQueryDisposable = userUtils.createOrUpdateUser(null, loginData.getToken(),
null, null, "", true,
null, currentUser.getId(), null, appPreferences.getTemporaryClientCertAlias(), null)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.as(AutoDispose.autoDisposable(getScopeProvider()))
.subscribe(userEntity -> {
if (finalMessageType != null) {
ApplicationWideMessageHolder.getInstance().setMessageType(finalMessageType);
}
OneTimeWorkRequest pushRegistrationWork = new OneTimeWorkRequest.Builder(PushRegistrationWorker.class).build();
WorkManager.getInstance().enqueue(pushRegistrationWork);
getRouter().popCurrentController();
}, throwable -> dispose(),
this::dispose);
}
} else {
if (finalMessageType != null) {
ApplicationWideMessageHolder.getInstance().setMessageType(finalMessageType);
}
getRouter().popToRoot();
}
webView.loadUrl("javascript: {" +
"document.getElementById('user').value = '" + username + "';" +
"document.getElementById('password').value = '" + password + "';" +
"document.getElementById('submit').click(); };");
}
}
}
private LoginData parseLoginData(String prefix, String dataString) {
if (dataString.length() < prefix.length()) {
return null;
}
}
LoginData loginData = new LoginData();
super.onPageFinished(view, url);
}
// format is xxx://login/server:xxx&user:xxx&password:xxx
String data = dataString.substring(prefix.length());
@Override
public void onReceivedClientCertRequest(WebView view, ClientCertRequest request) {
UserEntity userEntity = userUtils.getCurrentUser();
String[] values = data.split("&");
if (values.length != 3) {
return null;
String alias = null;
if (!isPasswordUpdate) {
alias = appPreferences.getTemporaryClientCertAlias();
}
for (String value : values) {
if (value.startsWith("user" + LOGIN_URL_DATA_KEY_VALUE_SEPARATOR)) {
loginData.setUsername(URLDecoder.decode(
value.substring(("user" + LOGIN_URL_DATA_KEY_VALUE_SEPARATOR).length())));
} else if (value.startsWith("password" + LOGIN_URL_DATA_KEY_VALUE_SEPARATOR)) {
loginData.setToken(URLDecoder.decode(
value.substring(("password" + LOGIN_URL_DATA_KEY_VALUE_SEPARATOR).length())));
} else if (value.startsWith("server" + LOGIN_URL_DATA_KEY_VALUE_SEPARATOR)) {
loginData.setServerUrl(URLDecoder.decode(
value.substring(("server" + LOGIN_URL_DATA_KEY_VALUE_SEPARATOR).length())));
} else {
return null;
if (TextUtils.isEmpty(alias) && (userEntity != null)) {
alias = userEntity.getClientCertificate();
}
if (!TextUtils.isEmpty(alias)) {
String finalAlias = alias;
new Thread(() -> {
try {
PrivateKey privateKey = KeyChain.getPrivateKey(getActivity(), finalAlias);
X509Certificate[] certificates =
KeyChain.getCertificateChain(getActivity(), finalAlias);
if (privateKey != null && certificates != null) {
request.proceed(privateKey, certificates);
} else {
request.cancel();
}
} catch (KeyChainException | InterruptedException e) {
request.cancel();
}
}
if (!TextUtils.isEmpty(loginData.getServerUrl()) && !TextUtils.isEmpty(loginData.getUsername()) &&
!TextUtils.isEmpty(loginData.getToken())) {
return loginData;
}).start();
} else {
return null;
KeyChain.choosePrivateKeyAlias(getActivity(), chosenAlias -> {
if (chosenAlias != null) {
appPreferences.setTemporaryClientCertAlias(chosenAlias);
new Thread(() -> {
PrivateKey privateKey = null;
try {
privateKey = KeyChain.getPrivateKey(getActivity(), chosenAlias);
X509Certificate[] certificates =
KeyChain.getCertificateChain(getActivity(), chosenAlias);
if (privateKey != null && certificates != null) {
request.proceed(privateKey, certificates);
} else {
request.cancel();
}
} catch (KeyChainException | InterruptedException e) {
request.cancel();
}
}).start();
} else {
request.cancel();
}
}, new String[] { "RSA", "EC" }, null, request.getHost(), request.getPort(), null);
}
}
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
try {
SslCertificate sslCertificate = error.getCertificate();
Field f = sslCertificate.getClass().getDeclaredField("mX509Certificate");
f.setAccessible(true);
X509Certificate cert = (X509Certificate) f.get(sslCertificate);
if (cert == null) {
handler.cancel();
} else {
try {
magicTrustManager.checkServerTrusted(new X509Certificate[] { cert }, "generic");
handler.proceed();
} catch (CertificateException exception) {
eventBus.post(new CertificateEvent(cert, magicTrustManager, handler));
}
}
} catch (Exception exception) {
handler.cancel();
}
}
@Override
public void onReceivedError(WebView view, int errorCode, String description,
String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
}
});
webView.loadUrl(baseUrl + "/index.php/login/flow", headers);
}
private void dispose() {
if (userQueryDisposable != null && !userQueryDisposable.isDisposed()) {
userQueryDisposable.dispose();
}
@Override
public void onDestroy() {
super.onDestroy();
dispose();
userQueryDisposable = null;
}
private void parseAndLoginFromWebView(String dataString) {
LoginData loginData = parseLoginData(assembledPrefix, dataString);
if (loginData != null) {
dispose();
UserEntity currentUser = userUtils.getCurrentUser();
ApplicationWideMessageHolder.MessageType messageType = null;
if (!isPasswordUpdate && userUtils.getIfUserWithUsernameAndServer(loginData.getUsername(),
baseUrl)) {
messageType = ApplicationWideMessageHolder.MessageType.ACCOUNT_UPDATED_NOT_ADDED;
}
if (userUtils.checkIfUserIsScheduledForDeletion(loginData.getUsername(), baseUrl)) {
ApplicationWideMessageHolder.getInstance().setMessageType(
ApplicationWideMessageHolder.MessageType.ACCOUNT_SCHEDULED_FOR_DELETION);
if (!isPasswordUpdate) {
getRouter().popToRoot();
} else {
getRouter().popCurrentController();
}
}
ApplicationWideMessageHolder.MessageType finalMessageType = messageType;
cookieManager.getCookieStore().removeAll();
if (!isPasswordUpdate && finalMessageType == null) {
Bundle bundle = new Bundle();
bundle.putString(BundleKeys.INSTANCE.getKEY_USERNAME(), loginData.getUsername());
bundle.putString(BundleKeys.INSTANCE.getKEY_TOKEN(), loginData.getToken());
bundle.putString(BundleKeys.INSTANCE.getKEY_BASE_URL(), loginData.getServerUrl());
String protocol = "";
if (baseUrl.startsWith("http://")) {
protocol = "http://";
} else if (baseUrl.startsWith("https://")) {
protocol = "https://";
}
if (!TextUtils.isEmpty(protocol)) {
bundle.putString(BundleKeys.INSTANCE.getKEY_ORIGINAL_PROTOCOL(), protocol);
}
getRouter().pushController(RouterTransaction.with(new AccountVerificationController
(bundle)).pushChangeHandler(new HorizontalChangeHandler())
.popChangeHandler(new HorizontalChangeHandler()));
} else {
if (isPasswordUpdate) {
if (currentUser != null) {
userQueryDisposable = userUtils.createOrUpdateUser(null, loginData.getToken(),
null, null, "", true,
null, currentUser.getId(), null, appPreferences.getTemporaryClientCertAlias(), null)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.as(AutoDispose.autoDisposable(getScopeProvider()))
.subscribe(userEntity -> {
if (finalMessageType != null) {
ApplicationWideMessageHolder.getInstance().setMessageType(finalMessageType);
}
OneTimeWorkRequest pushRegistrationWork =
new OneTimeWorkRequest.Builder(PushRegistrationWorker.class).build();
WorkManager.getInstance().enqueue(pushRegistrationWork);
getRouter().popCurrentController();
}, throwable -> dispose(),
this::dispose);
}
} else {
if (finalMessageType != null) {
ApplicationWideMessageHolder.getInstance().setMessageType(finalMessageType);
}
getRouter().popToRoot();
}
}
}
}
private LoginData parseLoginData(String prefix, String dataString) {
if (dataString.length() < prefix.length()) {
return null;
}
@Override
protected void onDestroyView(@NonNull View view) {
super.onDestroyView(view);
if (getActivity() != null) {
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
}
LoginData loginData = new LoginData();
// format is xxx://login/server:xxx&user:xxx&password:xxx
String data = dataString.substring(prefix.length());
String[] values = data.split("&");
if (values.length != 3) {
return null;
}
for (String value : values) {
if (value.startsWith("user" + LOGIN_URL_DATA_KEY_VALUE_SEPARATOR)) {
loginData.setUsername(URLDecoder.decode(
value.substring(("user" + LOGIN_URL_DATA_KEY_VALUE_SEPARATOR).length())));
} else if (value.startsWith("password" + LOGIN_URL_DATA_KEY_VALUE_SEPARATOR)) {
loginData.setToken(URLDecoder.decode(
value.substring(("password" + LOGIN_URL_DATA_KEY_VALUE_SEPARATOR).length())));
} else if (value.startsWith("server" + LOGIN_URL_DATA_KEY_VALUE_SEPARATOR)) {
loginData.setServerUrl(URLDecoder.decode(
value.substring(("server" + LOGIN_URL_DATA_KEY_VALUE_SEPARATOR).length())));
} else {
return null;
}
}
if (!TextUtils.isEmpty(loginData.getServerUrl())
&& !TextUtils.isEmpty(loginData.getUsername())
&&
!TextUtils.isEmpty(loginData.getToken())) {
return loginData;
} else {
return null;
}
}
@Override
public void onDestroy() {
super.onDestroy();
dispose();
}
@Override
protected void onDestroyView(@NonNull View view) {
super.onDestroyView(view);
if (getActivity() != null) {
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
}
}
}

View File

@ -31,27 +31,33 @@ import com.bluelinelabs.conductor.Controller
abstract class ButterKnifeController : Controller {
protected var unbinder: Unbinder? = null
protected var unbinder: Unbinder? = null
constructor()
constructor()
constructor(args: Bundle) : super(args)
protected abstract fun inflateView(inflater: LayoutInflater, container: ViewGroup): View
protected abstract fun inflateView(
inflater: LayoutInflater,
container: ViewGroup
): View
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup): View {
val view = inflateView(inflater, container)
unbinder = ButterKnife.bind(this, view)
onViewBound(view)
return view
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup
): View {
val view = inflateView(inflater, container)
unbinder = ButterKnife.bind(this, view)
onViewBound(view)
return view
}
protected open fun onViewBound(view: View) {}
protected open fun onViewBound(view: View) {}
override fun onDestroyView(view: View) {
super.onDestroyView(view)
unbinder!!.unbind()
unbinder = null
}
override fun onDestroyView(view: View) {
super.onDestroyView(view)
unbinder!!.unbind()
unbinder = null
}
}

View File

@ -21,5 +21,5 @@ package com.nextcloud.talk.controllers.base.providers;
import androidx.appcompat.app.ActionBar;
public interface ActionBarProvider {
ActionBar getSupportActionBar();
ActionBar getSupportActionBar();
}

View File

@ -64,266 +64,279 @@ import org.parceler.Parcels;
@AutoInjector(NextcloudTalkApplication.class)
public class EntryMenuController extends BaseController {
@BindView(R.id.ok_button)
Button proceedButton;
@BindView(R.id.ok_button)
Button proceedButton;
@BindView(R.id.text_edit)
EmojiTextInputEditText editText;
@BindView(R.id.text_edit)
EmojiTextInputEditText editText;
@BindView(R.id.text_input_layout)
TextInputLayout textInputLayout;
@BindView(R.id.text_input_layout)
TextInputLayout textInputLayout;
@BindView(R.id.smileyButton)
ImageView smileyButton;
@BindView(R.id.smileyButton)
ImageView smileyButton;
@Inject
EventBus eventBus;
@Inject
EventBus eventBus;
@Inject
UserUtils userUtils;
@Inject
UserUtils userUtils;
private int operationCode;
private Conversation conversation;
private Intent shareIntent;
private String packageName;
private String name;
private String callUrl;
private int operationCode;
private Conversation conversation;
private Intent shareIntent;
private String packageName;
private String name;
private String callUrl;
private EmojiPopup emojiPopup;
private EmojiPopup emojiPopup;
private Bundle originalBundle;
private Bundle originalBundle;
public EntryMenuController(Bundle args) {
super();
originalBundle = args;
public EntryMenuController(Bundle args) {
super();
originalBundle = args;
this.operationCode = args.getInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE());
if (args.containsKey(BundleKeys.INSTANCE.getKEY_ROOM())) {
this.conversation = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_ROOM()));
}
if (args.containsKey(BundleKeys.INSTANCE.getKEY_SHARE_INTENT())) {
this.shareIntent = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_SHARE_INTENT()));
}
this.name = args.getString(BundleKeys.INSTANCE.getKEY_APP_ITEM_NAME(), "");
this.packageName = args.getString(BundleKeys.INSTANCE.getKEY_APP_ITEM_PACKAGE_NAME(), "");
this.callUrl = args.getString(BundleKeys.INSTANCE.getKEY_CALL_URL(), "");
this.operationCode = args.getInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE());
if (args.containsKey(BundleKeys.INSTANCE.getKEY_ROOM())) {
this.conversation = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_ROOM()));
}
@Override
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
return inflater.inflate(R.layout.controller_entry_menu, container, false);
if (args.containsKey(BundleKeys.INSTANCE.getKEY_SHARE_INTENT())) {
this.shareIntent =
Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_SHARE_INTENT()));
}
@OnClick(R.id.smileyButton)
void onSmileyClick() {
emojiPopup.toggle();
this.name = args.getString(BundleKeys.INSTANCE.getKEY_APP_ITEM_NAME(), "");
this.packageName = args.getString(BundleKeys.INSTANCE.getKEY_APP_ITEM_PACKAGE_NAME(), "");
this.callUrl = args.getString(BundleKeys.INSTANCE.getKEY_CALL_URL(), "");
}
@Override
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
return inflater.inflate(R.layout.controller_entry_menu, container, false);
}
@OnClick(R.id.smileyButton)
void onSmileyClick() {
emojiPopup.toggle();
}
@Override
protected void onAttach(@NonNull View view) {
super.onAttach(view);
if (ApplicationWideMessageHolder.getInstance().getMessageType() != null &&
ApplicationWideMessageHolder.getInstance()
.getMessageType()
.equals(ApplicationWideMessageHolder.MessageType.CALL_PASSWORD_WRONG)) {
textInputLayout.setError(getResources().getString(R.string.nc_wrong_password));
ApplicationWideMessageHolder.getInstance().setMessageType(null);
if (proceedButton.isEnabled()) {
proceedButton.setEnabled(false);
proceedButton.setAlpha(0.7f);
}
}
}
@OnClick(R.id.ok_button)
public void onProceedButtonClick() {
Bundle bundle;
if (operationCode == 99) {
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
bundle = new Bundle();
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ROOM(), Parcels.wrap(conversation));
bundle.putString(BundleKeys.INSTANCE.getKEY_CALL_URL(), callUrl);
bundle.putString(BundleKeys.INSTANCE.getKEY_CONVERSATION_PASSWORD(),
editText.getText().toString());
bundle.putInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), operationCode);
if (originalBundle.containsKey(BundleKeys.INSTANCE.getKEY_SERVER_CAPABILITIES())) {
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_SERVER_CAPABILITIES(),
originalBundle.getParcelable(BundleKeys.INSTANCE.getKEY_SERVER_CAPABILITIES()));
}
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle))
.pushChangeHandler(new HorizontalChangeHandler())
.popChangeHandler(new HorizontalChangeHandler()));
} else if (operationCode != 7 && operationCode != 10 && operationCode != 11) {
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
bundle = new Bundle();
if (operationCode == 4 || operationCode == 6) {
conversation.setPassword(editText.getText().toString());
} else {
conversation.setName(editText.getText().toString());
}
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ROOM(), Parcels.wrap(conversation));
bundle.putInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), operationCode);
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle))
.pushChangeHandler(new HorizontalChangeHandler())
.popChangeHandler(new HorizontalChangeHandler()));
} else if (operationCode == 7) {
if (getActivity() != null) {
shareIntent.putExtra(Intent.EXTRA_TEXT, ShareUtils.getStringForIntent(getActivity(),
editText.getText().toString(), userUtils, conversation));
Intent intent = new Intent(shareIntent);
intent.setComponent(new ComponentName(packageName, name));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getActivity().startActivity(intent);
eventBus.post(new BottomSheetLockEvent(true, 0, false, true));
}
} else if (operationCode != 11) {
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
bundle = new Bundle();
bundle.putInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), operationCode);
bundle.putString(BundleKeys.INSTANCE.getKEY_CALL_URL(), editText.getText().toString());
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle))
.pushChangeHandler(new HorizontalChangeHandler())
.popChangeHandler(new HorizontalChangeHandler()));
} else if (operationCode == 11) {
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
originalBundle.putString(BundleKeys.INSTANCE.getKEY_CONVERSATION_NAME(),
editText.getText().toString());
getRouter().pushController(
RouterTransaction.with(new OperationsMenuController(originalBundle))
.pushChangeHandler(new HorizontalChangeHandler())
.popChangeHandler(new HorizontalChangeHandler()));
}
}
@Override
protected void onViewBound(@NonNull View view) {
super.onViewBound(view);
NextcloudTalkApplication.Companion.getSharedApplication()
.getComponentApplication()
.inject(this);
if (conversation != null && operationCode == 2) {
editText.setText(conversation.getName());
}
@Override
protected void onAttach(@NonNull View view) {
super.onAttach(view);
if (ApplicationWideMessageHolder.getInstance().getMessageType() != null &&
ApplicationWideMessageHolder.getInstance().getMessageType().equals(ApplicationWideMessageHolder.MessageType.CALL_PASSWORD_WRONG)) {
textInputLayout.setError(getResources().getString(R.string.nc_wrong_password));
ApplicationWideMessageHolder.getInstance().setMessageType(null);
if (proceedButton.isEnabled()) {
proceedButton.setEnabled(false);
proceedButton.setAlpha(0.7f);
}
}
}
editText.setOnEditorActionListener((v, actionId, event) -> {
if (actionId == EditorInfo.IME_ACTION_DONE
&& proceedButton != null
&& proceedButton.isEnabled()) {
proceedButton.callOnClick();
return true;
}
return false;
});
@OnClick(R.id.ok_button)
public void onProceedButtonClick() {
Bundle bundle;
if (operationCode == 99) {
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
bundle = new Bundle();
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ROOM(), Parcels.wrap(conversation));
bundle.putString(BundleKeys.INSTANCE.getKEY_CALL_URL(), callUrl);
bundle.putString(BundleKeys.INSTANCE.getKEY_CONVERSATION_PASSWORD(), editText.getText().toString());
bundle.putInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), operationCode);
if (originalBundle.containsKey(BundleKeys.INSTANCE.getKEY_SERVER_CAPABILITIES())) {
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_SERVER_CAPABILITIES(), originalBundle.getParcelable(BundleKeys.INSTANCE.getKEY_SERVER_CAPABILITIES()));
}
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle))
.pushChangeHandler(new HorizontalChangeHandler())
.popChangeHandler(new HorizontalChangeHandler()));
} else if (operationCode != 7 && operationCode != 10 && operationCode != 11) {
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
bundle = new Bundle();
if (operationCode == 4 || operationCode == 6) {
conversation.setPassword(editText.getText().toString());
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
if (!TextUtils.isEmpty(s)) {
if (operationCode == 2) {
if (conversation.getName() == null || !conversation.getName().equals(s.toString())) {
if (!proceedButton.isEnabled()) {
proceedButton.setEnabled(true);
proceedButton.setAlpha(1.0f);
}
textInputLayout.setErrorEnabled(false);
} else {
conversation.setName(editText.getText().toString());
if (proceedButton.isEnabled()) {
proceedButton.setEnabled(false);
proceedButton.setAlpha(0.38f);
}
textInputLayout.setError(getResources().getString(R.string.nc_call_name_is_same));
}
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ROOM(), Parcels.wrap(conversation));
bundle.putInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), operationCode);
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle))
.pushChangeHandler(new HorizontalChangeHandler())
.popChangeHandler(new HorizontalChangeHandler()));
} else if (operationCode == 7) {
if (getActivity() != null) {
shareIntent.putExtra(Intent.EXTRA_TEXT, ShareUtils.getStringForIntent(getActivity(),
editText.getText().toString(), userUtils, conversation));
Intent intent = new Intent(shareIntent);
intent.setComponent(new ComponentName(packageName, name));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getActivity().startActivity(intent);
eventBus.post(new BottomSheetLockEvent(true, 0, false, true));
} else if (operationCode != 10) {
if (!proceedButton.isEnabled()) {
proceedButton.setEnabled(true);
proceedButton.setAlpha(1.0f);
}
} else if (operationCode != 11) {
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
bundle = new Bundle();
bundle.putInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), operationCode);
bundle.putString(BundleKeys.INSTANCE.getKEY_CALL_URL(), editText.getText().toString());
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle))
.pushChangeHandler(new HorizontalChangeHandler())
.popChangeHandler(new HorizontalChangeHandler()));
} else if (operationCode == 11) {
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
originalBundle.putString(BundleKeys.INSTANCE.getKEY_CONVERSATION_NAME(), editText.getText().toString());
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(originalBundle))
.pushChangeHandler(new HorizontalChangeHandler())
.popChangeHandler(new HorizontalChangeHandler()));
textInputLayout.setErrorEnabled(false);
} else if ((editText.getText().toString().startsWith("http://") ||
editText.getText().toString().startsWith("https://")) &&
editText.getText().toString().contains("/call/")) {
// operation code 10
if (!proceedButton.isEnabled()) {
proceedButton.setEnabled(true);
proceedButton.setAlpha(1.0f);
}
textInputLayout.setErrorEnabled(false);
} else {
if (proceedButton.isEnabled()) {
proceedButton.setEnabled(false);
proceedButton.setAlpha(0.38f);
}
textInputLayout.setError(getResources().getString(R.string.nc_wrong_link));
}
} else {
if (proceedButton.isEnabled()) {
proceedButton.setEnabled(false);
proceedButton.setAlpha(0.38f);
}
textInputLayout.setErrorEnabled(false);
}
}
}
});
@Override
protected void onViewBound(@NonNull View view) {
super.onViewBound(view);
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
if (conversation != null && operationCode == 2) {
editText.setText(conversation.getName());
}
editText.setOnEditorActionListener((v, actionId, event) -> {
if (actionId == EditorInfo.IME_ACTION_DONE && proceedButton != null && proceedButton.isEnabled()) {
proceedButton.callOnClick();
return true;
}
return false;
});
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
if (!TextUtils.isEmpty(s)) {
if (operationCode == 2) {
if (conversation.getName() == null || !conversation.getName().equals(s.toString())) {
if (!proceedButton.isEnabled()) {
proceedButton.setEnabled(true);
proceedButton.setAlpha(1.0f);
}
textInputLayout.setErrorEnabled(false);
} else {
if (proceedButton.isEnabled()) {
proceedButton.setEnabled(false);
proceedButton.setAlpha(0.38f);
}
textInputLayout.setError(getResources().getString(R.string.nc_call_name_is_same));
}
} else if (operationCode != 10) {
if (!proceedButton.isEnabled()) {
proceedButton.setEnabled(true);
proceedButton.setAlpha(1.0f);
}
textInputLayout.setErrorEnabled(false);
} else if ((editText.getText().toString().startsWith("http://") ||
editText.getText().toString().startsWith("https://")) &&
editText.getText().toString().contains("/call/")) {
// operation code 10
if (!proceedButton.isEnabled()) {
proceedButton.setEnabled(true);
proceedButton.setAlpha(1.0f);
}
textInputLayout.setErrorEnabled(false);
} else {
if (proceedButton.isEnabled()) {
proceedButton.setEnabled(false);
proceedButton.setAlpha(0.38f);
}
textInputLayout.setError(getResources().getString(R.string.nc_wrong_link));
}
} else {
if (proceedButton.isEnabled()) {
proceedButton.setEnabled(false);
proceedButton.setAlpha(0.38f);
}
textInputLayout.setErrorEnabled(false);
String labelText = "";
switch (operationCode) {
case 11:
case 2:
labelText = getResources().getString(R.string.nc_call_name);
editText.setInputType(InputType.TYPE_CLASS_TEXT);
smileyButton.setVisibility(View.VISIBLE);
emojiPopup = EmojiPopup.Builder.fromRootView(view)
.setOnEmojiPopupShownListener(new OnEmojiPopupShownListener() {
@Override
public void onEmojiPopupShown() {
if (getResources() != null) {
smileyButton.setColorFilter(getResources().getColor(R.color.colorPrimary),
PorterDuff.Mode.SRC_IN);
}
}
});
}
})
.setOnEmojiPopupDismissListener(new OnEmojiPopupDismissListener() {
@Override
public void onEmojiPopupDismiss() {
if (smileyButton != null) {
smileyButton.setColorFilter(getResources().getColor(R.color.emoji_icons),
PorterDuff.Mode.SRC_IN);
}
}
})
.setOnEmojiClickListener(new OnEmojiClickListener() {
@Override
public void onEmojiClick(@NonNull EmojiImageView emoji, @NonNull Emoji imageView) {
editText.getEditableText().append(" ");
}
})
.build(editText);
String labelText = "";
switch (operationCode) {
case 11:
case 2:
labelText = getResources().getString(R.string.nc_call_name);
editText.setInputType(InputType.TYPE_CLASS_TEXT);
smileyButton.setVisibility(View.VISIBLE);
emojiPopup = EmojiPopup.Builder.fromRootView(view).setOnEmojiPopupShownListener(new OnEmojiPopupShownListener() {
@Override
public void onEmojiPopupShown() {
if (getResources() != null) {
smileyButton.setColorFilter(getResources().getColor(R.color.colorPrimary),
PorterDuff.Mode.SRC_IN);
}
}
}).setOnEmojiPopupDismissListener(new OnEmojiPopupDismissListener() {
@Override
public void onEmojiPopupDismiss() {
if (smileyButton != null) {
smileyButton.setColorFilter(getResources().getColor(R.color.emoji_icons),
PorterDuff.Mode.SRC_IN);
}
}
}).setOnEmojiClickListener(new OnEmojiClickListener() {
@Override
public void onEmojiClick(@NonNull EmojiImageView emoji, @NonNull Emoji imageView) {
editText.getEditableText().append(" ");
}
}).build(editText);
break;
case 4:
labelText = getResources().getString(R.string.nc_new_password);
editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
break;
case 6:
case 7:
case 99:
// 99 is joining a conversation via password
labelText = getResources().getString(R.string.nc_password);
editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
break;
case 10:
labelText = getResources().getString(R.string.nc_conversation_link);
editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI);
break;
default:
break;
}
textInputLayout.setPasswordVisibilityToggleEnabled(operationCode == 99 || operationCode == 4 || operationCode == 6 || operationCode == 7);
textInputLayout.setHint(labelText);
textInputLayout.requestFocus();
break;
case 4:
labelText = getResources().getString(R.string.nc_new_password);
editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
break;
case 6:
case 7:
case 99:
// 99 is joining a conversation via password
labelText = getResources().getString(R.string.nc_password);
editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
break;
case 10:
labelText = getResources().getString(R.string.nc_conversation_link);
editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI);
break;
default:
break;
}
textInputLayout.setPasswordVisibilityToggleEnabled(
operationCode == 99 || operationCode == 4 || operationCode == 6 || operationCode == 7);
textInputLayout.setHint(labelText);
textInputLayout.requestFocus();
}
}

View File

@ -24,15 +24,16 @@ import android.widget.ImageView
import androidx.annotation.DrawableRes
interface ListItemWithImage {
val title: String
fun populateIcon(imageView: ImageView)
val title: String
fun populateIcon(imageView: ImageView)
}
data class BasicListItemWithImage(
@DrawableRes val iconRes: Int,
override val title: String) : ListItemWithImage {
@DrawableRes val iconRes: Int,
override val title: String
) : ListItemWithImage {
override fun populateIcon(imageView: ImageView) {
imageView.setImageResource(iconRes)
}
override fun populateIcon(imageView: ImageView) {
imageView.setImageResource(iconRes)
}
}

View File

@ -38,112 +38,117 @@ import com.nextcloud.talk.R
private const val KEY_ACTIVATED_INDEX = "activated_index"
internal class ListItemViewHolder(
itemView: View,
private val adapter: ListIconDialogAdapter<*>) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
init {
itemView.setOnClickListener(this)
}
itemView: View,
private val adapter: ListIconDialogAdapter<*>
) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
init {
itemView.setOnClickListener(this)
}
val iconView: ImageView = itemView.findViewById(R.id.icon)
val titleView: RtlTextView = itemView.findViewById(R.id.title)
val iconView: ImageView = itemView.findViewById(R.id.icon)
val titleView: RtlTextView = itemView.findViewById(R.id.title)
override fun onClick(view: View) = adapter.itemClicked(adapterPosition)
override fun onClick(view: View) = adapter.itemClicked(adapterPosition)
}
internal class ListIconDialogAdapter<IT : ListItemWithImage>(
private var dialog: MaterialDialog,
private var items: List<IT>,
disabledItems: IntArray?,
private var waitForPositiveButton: Boolean,
private var selection: ListItemListener<IT>) : RecyclerView.Adapter<ListItemViewHolder>(), DialogAdapter<IT, ListItemListener<IT>> {
private var dialog: MaterialDialog,
private var items: List<IT>,
disabledItems: IntArray?,
private var waitForPositiveButton: Boolean,
private var selection: ListItemListener<IT>
) : RecyclerView.Adapter<ListItemViewHolder>(), DialogAdapter<IT, ListItemListener<IT>> {
private var disabledIndices: IntArray = disabledItems ?: IntArray(0)
private var disabledIndices: IntArray = disabledItems ?: IntArray(0)
fun itemClicked(index: Int) {
if (waitForPositiveButton && dialog.hasActionButton(WhichButton.POSITIVE)) {
// Wait for positive action button, mark clicked item as activated so that we can call the
// selection listener when the button is pressed.
val lastActivated = dialog.config[KEY_ACTIVATED_INDEX] as? Int
dialog.config[KEY_ACTIVATED_INDEX] = index
if (lastActivated != null) {
notifyItemChanged(lastActivated)
}
notifyItemChanged(index)
} else {
// Don't wait for action buttons, call listener and dismiss if auto dismiss is applicable
this.selection?.invoke(dialog, index, this.items[index])
if (dialog.autoDismissEnabled && !dialog.hasActionButtons()) {
dialog.dismiss()
}
}
fun itemClicked(index: Int) {
if (waitForPositiveButton && dialog.hasActionButton(WhichButton.POSITIVE)) {
// Wait for positive action button, mark clicked item as activated so that we can call the
// selection listener when the button is pressed.
val lastActivated = dialog.config[KEY_ACTIVATED_INDEX] as? Int
dialog.config[KEY_ACTIVATED_INDEX] = index
if (lastActivated != null) {
notifyItemChanged(lastActivated)
}
notifyItemChanged(index)
} else {
// Don't wait for action buttons, call listener and dismiss if auto dismiss is applicable
this.selection?.invoke(dialog, index, this.items[index])
if (dialog.autoDismissEnabled && !dialog.hasActionButtons()) {
dialog.dismiss()
}
}
}
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int): ListItemViewHolder {
val listItemView: View = parent.inflate(dialog.windowContext, R.layout.menu_item_sheet)
val viewHolder = ListItemViewHolder(
itemView = listItemView,
adapter = this
)
viewHolder.titleView.maybeSetTextColor(dialog.windowContext, R.attr.md_color_content)
return viewHolder
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): ListItemViewHolder {
val listItemView: View = parent.inflate(dialog.windowContext, R.layout.menu_item_sheet)
val viewHolder = ListItemViewHolder(
itemView = listItemView,
adapter = this
)
viewHolder.titleView.maybeSetTextColor(dialog.windowContext, R.attr.md_color_content)
return viewHolder
}
override fun getItemCount() = items.size
override fun onBindViewHolder(
holder: ListItemViewHolder,
position: Int
) {
holder.itemView.isEnabled = !disabledIndices.contains(position)
val currentItem = items[position]
holder.titleView.text = currentItem.title
holder.itemView.background = dialog.getItemSelector()
currentItem.populateIcon(holder.iconView)
val activatedIndex = dialog.config[KEY_ACTIVATED_INDEX] as? Int
holder.itemView.isActivated = activatedIndex != null && activatedIndex == position
if (dialog.bodyFont != null) {
holder.titleView.typeface = dialog.bodyFont
}
}
override fun getItemCount() = items.size
override fun onBindViewHolder(
holder: ListItemViewHolder,
position: Int) {
holder.itemView.isEnabled = !disabledIndices.contains(position)
val currentItem = items[position]
holder.titleView.text = currentItem.title
holder.itemView.background = dialog.getItemSelector()
currentItem.populateIcon(holder.iconView)
val activatedIndex = dialog.config[KEY_ACTIVATED_INDEX] as? Int
holder.itemView.isActivated = activatedIndex != null && activatedIndex == position
if (dialog.bodyFont != null) {
holder.titleView.typeface = dialog.bodyFont
}
override fun positiveButtonClicked() {
val activatedIndex = dialog.config[KEY_ACTIVATED_INDEX] as? Int
if (activatedIndex != null) {
selection?.invoke(dialog, activatedIndex, items[activatedIndex])
dialog.config.remove(KEY_ACTIVATED_INDEX)
}
}
override fun positiveButtonClicked() {
val activatedIndex = dialog.config[KEY_ACTIVATED_INDEX] as? Int
if (activatedIndex != null) {
selection?.invoke(dialog, activatedIndex, items[activatedIndex])
dialog.config.remove(KEY_ACTIVATED_INDEX)
}
override fun replaceItems(
items: List<IT>,
listener: ListItemListener<IT>
) {
this.items = items
if (listener != null) {
this.selection = listener
}
this.notifyDataSetChanged()
}
override fun replaceItems(
items: List<IT>,
listener: ListItemListener<IT>) {
this.items = items
if (listener != null) {
this.selection = listener
}
this.notifyDataSetChanged()
}
override fun disableItems(indices: IntArray) {
this.disabledIndices = indices
notifyDataSetChanged()
}
override fun disableItems(indices: IntArray) {
this.disabledIndices = indices
notifyDataSetChanged()
}
override fun checkItems(indices: IntArray) = Unit
override fun checkItems(indices: IntArray) = Unit
override fun uncheckItems(indices: IntArray) = Unit
override fun uncheckItems(indices: IntArray) = Unit
override fun toggleItems(indices: IntArray) = Unit
override fun toggleItems(indices: IntArray) = Unit
override fun checkAllItems() = Unit
override fun checkAllItems() = Unit
override fun uncheckAllItems() = Unit
override fun uncheckAllItems() = Unit
override fun toggleAllChecked() = Unit
override fun toggleAllChecked() = Unit
override fun isItemChecked(index: Int) = false
override fun isItemChecked(index: Int) = false
}

View File

@ -28,48 +28,50 @@ import com.afollestad.materialdialogs.list.customListAdapter
import com.afollestad.materialdialogs.list.getListAdapter
typealias ListItemListener<IT> =
((dialog: MaterialDialog, index: Int, item: IT) -> Unit)?
((dialog: MaterialDialog, index: Int, item: IT) -> Unit)?
@CheckResult fun <IT : ListItemWithImage> MaterialDialog.listItemsWithImage(
items: List<IT>,
disabledIndices: IntArray? = null,
waitForPositiveButton: Boolean = true,
selection: ListItemListener<IT> = null): MaterialDialog {
items: List<IT>,
disabledIndices: IntArray? = null,
waitForPositiveButton: Boolean = true,
selection: ListItemListener<IT> = null
): MaterialDialog {
if (getListAdapter() != null) {
return updateListItemsWithImage(
items = items,
disabledIndices = disabledIndices
)
}
val layoutManager = LinearLayoutManager(windowContext)
return customListAdapter(
adapter = ListIconDialogAdapter(
dialog = this,
items = items,
disabledItems = disabledIndices,
waitForPositiveButton = waitForPositiveButton,
selection = selection
),
layoutManager = layoutManager
if (getListAdapter() != null) {
return updateListItemsWithImage(
items = items,
disabledIndices = disabledIndices
)
}
val layoutManager = LinearLayoutManager(windowContext)
return customListAdapter(
adapter = ListIconDialogAdapter(
dialog = this,
items = items,
disabledItems = disabledIndices,
waitForPositiveButton = waitForPositiveButton,
selection = selection
),
layoutManager = layoutManager
)
}
fun MaterialDialog.updateListItemsWithImage(
items: List<ListItemWithImage>,
disabledIndices: IntArray? = null): MaterialDialog {
val adapter = getListAdapter()
check(adapter != null) {
"updateGridItems(...) can't be used before you've created a bottom sheet grid dialog."
}
if (adapter is DialogAdapter<*, *>) {
@Suppress("UNCHECKED_CAST")
(adapter as DialogAdapter<ListItemWithImage, *>).replaceItems(items)
items: List<ListItemWithImage>,
disabledIndices: IntArray? = null
): MaterialDialog {
val adapter = getListAdapter()
check(adapter != null) {
"updateGridItems(...) can't be used before you've created a bottom sheet grid dialog."
}
if (adapter is DialogAdapter<*, *>) {
@Suppress("UNCHECKED_CAST")
(adapter as DialogAdapter<ListItemWithImage, *>).replaceItems(items)
if (disabledIndices != null) {
adapter.disableItems(disabledIndices)
}
if (disabledIndices != null) {
adapter.disableItems(disabledIndices)
}
return this
}
return this
}

View File

@ -28,9 +28,9 @@ import org.greenrobot.eventbus.EventBus;
@Module
public class BusModule {
@Provides
@Singleton
public EventBus provideEventBus() {
return EventBus.getDefault();
}
@Provides
@Singleton
public EventBus provideEventBus() {
return EventBus.getDefault();
}
}

View File

@ -27,14 +27,14 @@ import dagger.Provides;
@Module
public class ContextModule {
private final Context context;
private final Context context;
public ContextModule(@NonNull final Context context) {
this.context = context;
}
public ContextModule(@NonNull final Context context) {
this.context = context;
}
@Provides
public Context provideContext() {
return context;
}
@Provides
public Context provideContext() {
return context;
}
}

View File

@ -39,25 +39,26 @@ import net.orange_box.storebox.StoreBox;
@Module
public class DatabaseModule {
@Provides
@Singleton
public SqlCipherDatabaseSource provideSqlCipherDatabaseSource(@NonNull final Context context) {
return new SqlCipherDatabaseSource(context, Models.DEFAULT,
context.getResources().getString(R.string.nc_app_name).toLowerCase()
.replace(" ", "_").trim() + ".sqlite",
context.getString(R.string.nc_talk_database_encryption_key), 6);
}
@Provides
@Singleton
public SqlCipherDatabaseSource provideSqlCipherDatabaseSource(@NonNull final Context context) {
return new SqlCipherDatabaseSource(context, Models.DEFAULT,
context.getResources().getString(R.string.nc_app_name).toLowerCase()
.replace(" ", "_").trim() + ".sqlite",
context.getString(R.string.nc_talk_database_encryption_key), 6);
}
@Provides
@Singleton
public ReactiveEntityStore<Persistable> provideDataStore(@NonNull final SqlCipherDatabaseSource sqlCipherDatabaseSource) {
final Configuration configuration = sqlCipherDatabaseSource.getConfiguration();
return ReactiveSupport.toReactiveStore(new EntityDataStore<Persistable>(configuration));
}
@Provides
@Singleton
public ReactiveEntityStore<Persistable> provideDataStore(
@NonNull final SqlCipherDatabaseSource sqlCipherDatabaseSource) {
final Configuration configuration = sqlCipherDatabaseSource.getConfiguration();
return ReactiveSupport.toReactiveStore(new EntityDataStore<Persistable>(configuration));
}
@Provides
@Singleton
public AppPreferences providePreferences(@NonNull final Context poContext) {
return StoreBox.create(poContext, AppPreferences.class);
}
@Provides
@Singleton
public AppPreferences providePreferences(@NonNull final Context poContext) {
return StoreBox.create(poContext, AppPreferences.class);
}
}

View File

@ -73,250 +73,253 @@ import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
@Module(includes = DatabaseModule.class)
public class RestModule {
private static final String TAG = "RestModule";
private final Context context;
private static final String TAG = "RestModule";
private final Context context;
public RestModule(Context context) {
this.context = context;
public RestModule(Context context) {
this.context = context;
}
@Singleton
@Provides
NcApi provideNcApi(Retrofit retrofit) {
return retrofit.create(NcApi.class);
}
@Singleton
@Provides
Proxy provideProxy(AppPreferences appPreferences) {
if (!TextUtils.isEmpty(appPreferences.getProxyType()) && !"No proxy".equals(
appPreferences.getProxyType())
&& !TextUtils.isEmpty(appPreferences.getProxyHost())) {
GetProxyRunnable getProxyRunnable = new GetProxyRunnable(appPreferences);
Thread getProxyThread = new Thread(getProxyRunnable);
getProxyThread.start();
try {
getProxyThread.join();
return getProxyRunnable.getProxyValue();
} catch (InterruptedException e) {
Log.e(TAG, "Failed to join the thread while getting proxy: " + e.getLocalizedMessage());
return Proxy.NO_PROXY;
}
} else {
return Proxy.NO_PROXY;
}
}
@Singleton
@Provides
Retrofit provideRetrofit(OkHttpClient httpClient) {
Retrofit.Builder retrofitBuilder = new Retrofit.Builder()
.client(httpClient)
.baseUrl("https://nextcloud.com")
.addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
.addConverterFactory(LoganSquareConverterFactory.create());
return retrofitBuilder.build();
}
@Singleton
@Provides
MagicTrustManager provideMagicTrustManager() {
return new MagicTrustManager();
}
@Singleton
@Provides
MagicKeyManager provideKeyManager(AppPreferences appPreferences, UserUtils userUtils) {
KeyStore keyStore = null;
try {
keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
KeyManagerFactory kmf =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keyStore, null);
X509KeyManager origKm = (X509KeyManager) kmf.getKeyManagers()[0];
return new MagicKeyManager(origKm, userUtils, appPreferences);
} catch (KeyStoreException e) {
Log.e(TAG, "KeyStoreException " + e.getLocalizedMessage());
} catch (CertificateException e) {
Log.e(TAG, "CertificateException " + e.getLocalizedMessage());
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, "NoSuchAlgorithmException " + e.getLocalizedMessage());
} catch (IOException e) {
Log.e(TAG, "IOException " + e.getLocalizedMessage());
} catch (UnrecoverableKeyException e) {
Log.e(TAG, "UnrecoverableKeyException " + e.getLocalizedMessage());
}
@Singleton
@Provides
NcApi provideNcApi(Retrofit retrofit) {
return retrofit.create(NcApi.class);
return null;
}
@Singleton
@Provides
SSLSocketFactoryCompat provideSslSocketFactoryCompat(MagicKeyManager keyManager, MagicTrustManager
magicTrustManager) {
return new SSLSocketFactoryCompat(keyManager, magicTrustManager);
}
@Singleton
@Provides
CookieManager provideCookieManager() {
CookieManager cookieManager = new CookieManager();
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_NONE);
return cookieManager;
}
@Singleton
@Provides
Cache provideCache() {
int cacheSize = 128 * 1024 * 1024; // 128 MB
return new Cache(NextcloudTalkApplication.Companion.getSharedApplication().getCacheDir(),
cacheSize);
}
@Singleton
@Provides
Dispatcher provideDispatcher() {
Dispatcher dispatcher = new Dispatcher();
dispatcher.setMaxRequestsPerHost(100);
dispatcher.setMaxRequests(100);
return dispatcher;
}
@Singleton
@Provides
OkHttpClient provideHttpClient(Proxy proxy, AppPreferences appPreferences,
MagicTrustManager magicTrustManager,
SSLSocketFactoryCompat sslSocketFactoryCompat, Cache cache,
CookieManager cookieManager, Dispatcher dispatcher) {
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.retryOnConnectionFailure(true);
httpClient.connectTimeout(45, TimeUnit.SECONDS);
httpClient.readTimeout(45, TimeUnit.SECONDS);
httpClient.writeTimeout(45, TimeUnit.SECONDS);
httpClient.cookieJar(new JavaNetCookieJar(cookieManager));
httpClient.cache(cache);
// Trust own CA and all self-signed certs
httpClient.sslSocketFactory(sslSocketFactoryCompat, magicTrustManager);
httpClient.retryOnConnectionFailure(true);
httpClient.hostnameVerifier(magicTrustManager.getHostnameVerifier(OkHostnameVerifier.INSTANCE));
httpClient.dispatcher(dispatcher);
if (!Proxy.NO_PROXY.equals(proxy)) {
httpClient.proxy(proxy);
if (appPreferences.getProxyCredentials() &&
!TextUtils.isEmpty(appPreferences.getProxyUsername()) &&
!TextUtils.isEmpty(appPreferences.getProxyPassword())) {
httpClient.proxyAuthenticator(new MagicAuthenticator(Credentials.basic(
appPreferences.getProxyUsername(),
appPreferences.getProxyPassword()), "Proxy-Authorization"));
}
}
@Singleton
@Provides
Proxy provideProxy(AppPreferences appPreferences) {
if (!TextUtils.isEmpty(appPreferences.getProxyType()) && !"No proxy".equals(appPreferences.getProxyType())
&& !TextUtils.isEmpty(appPreferences.getProxyHost())) {
GetProxyRunnable getProxyRunnable = new GetProxyRunnable(appPreferences);
Thread getProxyThread = new Thread(getProxyRunnable);
getProxyThread.start();
try {
getProxyThread.join();
return getProxyRunnable.getProxyValue();
} catch (InterruptedException e) {
Log.e(TAG, "Failed to join the thread while getting proxy: " + e.getLocalizedMessage());
return Proxy.NO_PROXY;
}
} else {
return Proxy.NO_PROXY;
}
httpClient.addInterceptor(new HeadersInterceptor());
if (BuildConfig.DEBUG && !context.getResources().getBoolean(R.bool.nc_is_debug)) {
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
loggingInterceptor.redactHeader("Authorization");
loggingInterceptor.redactHeader("Proxy-Authorization");
httpClient.addInterceptor(loggingInterceptor);
} else if (context.getResources().getBoolean(R.bool.nc_is_debug)) {
HttpLoggingInterceptor.Logger fileLogger =
s -> LoggingUtils.INSTANCE.writeLogEntryToFile(context, s);
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(fileLogger);
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
loggingInterceptor.redactHeader("Authorization");
loggingInterceptor.redactHeader("Proxy-Authorization");
httpClient.addInterceptor(loggingInterceptor);
}
@Singleton
@Provides
Retrofit provideRetrofit(OkHttpClient httpClient) {
Retrofit.Builder retrofitBuilder = new Retrofit.Builder()
.client(httpClient)
.baseUrl("https://nextcloud.com")
.addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
.addConverterFactory(LoganSquareConverterFactory.create());
return httpClient.build();
}
return retrofitBuilder.build();
public static class HeadersInterceptor implements Interceptor {
@NonNull
@Override
public Response intercept(@NonNull Chain chain) throws IOException {
Request original = chain.request();
Request request = original.newBuilder()
.header("User-Agent", ApiUtils.getUserAgent())
.header("Accept", "application/json")
.header("OCS-APIRequest", "true")
.method(original.method(), original.body())
.build();
Response response = chain.proceed(request);
if (request.url().encodedPath().contains("/avatar/")) {
AvatarStatusCodeHolder.getInstance().setStatusCode(response.code());
}
return response;
}
}
public static class MagicAuthenticator implements Authenticator {
private String credentials;
private String authenticatorType;
public MagicAuthenticator(@NonNull String credentials, @NonNull String authenticatorType) {
this.credentials = credentials;
this.authenticatorType = authenticatorType;
}
@Singleton
@Provides
MagicTrustManager provideMagicTrustManager() {
return new MagicTrustManager();
}
@Singleton
@Provides
MagicKeyManager provideKeyManager(AppPreferences appPreferences, UserUtils userUtils) {
KeyStore keyStore = null;
try {
keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keyStore, null);
X509KeyManager origKm = (X509KeyManager) kmf.getKeyManagers()[0];
return new MagicKeyManager(origKm, userUtils, appPreferences);
} catch (KeyStoreException e) {
Log.e(TAG, "KeyStoreException " + e.getLocalizedMessage());
} catch (CertificateException e) {
Log.e(TAG, "CertificateException " + e.getLocalizedMessage());
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, "NoSuchAlgorithmException " + e.getLocalizedMessage());
} catch (IOException e) {
Log.e(TAG, "IOException " + e.getLocalizedMessage());
} catch (UnrecoverableKeyException e) {
Log.e(TAG, "UnrecoverableKeyException " + e.getLocalizedMessage());
}
@Nullable
@Override
public Request authenticate(@Nullable Route route, @NonNull Response response) {
if (response.request().header(authenticatorType) != null) {
return null;
}
}
@Singleton
@Provides
SSLSocketFactoryCompat provideSslSocketFactoryCompat(MagicKeyManager keyManager, MagicTrustManager
magicTrustManager) {
return new SSLSocketFactoryCompat(keyManager, magicTrustManager);
}
Response countedResponse = response;
@Singleton
@Provides
CookieManager provideCookieManager() {
CookieManager cookieManager = new CookieManager();
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_NONE);
return cookieManager;
}
int attemptsCount = 0;
@Singleton
@Provides
Cache provideCache() {
int cacheSize = 128 * 1024 * 1024; // 128 MB
return new Cache(NextcloudTalkApplication.Companion.getSharedApplication().getCacheDir(), cacheSize);
}
@Singleton
@Provides
Dispatcher provideDispatcher() {
Dispatcher dispatcher = new Dispatcher();
dispatcher.setMaxRequestsPerHost(100);
dispatcher.setMaxRequests(100);
return dispatcher;
}
@Singleton
@Provides
OkHttpClient provideHttpClient(Proxy proxy, AppPreferences appPreferences,
MagicTrustManager magicTrustManager,
SSLSocketFactoryCompat sslSocketFactoryCompat, Cache cache,
CookieManager cookieManager, Dispatcher dispatcher) {
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.retryOnConnectionFailure(true);
httpClient.connectTimeout(45, TimeUnit.SECONDS);
httpClient.readTimeout(45, TimeUnit.SECONDS);
httpClient.writeTimeout(45, TimeUnit.SECONDS);
httpClient.cookieJar(new JavaNetCookieJar(cookieManager));
httpClient.cache(cache);
// Trust own CA and all self-signed certs
httpClient.sslSocketFactory(sslSocketFactoryCompat, magicTrustManager);
httpClient.retryOnConnectionFailure(true);
httpClient.hostnameVerifier(magicTrustManager.getHostnameVerifier(OkHostnameVerifier.INSTANCE));
httpClient.dispatcher(dispatcher);
if (!Proxy.NO_PROXY.equals(proxy)) {
httpClient.proxy(proxy);
if (appPreferences.getProxyCredentials() &&
!TextUtils.isEmpty(appPreferences.getProxyUsername()) &&
!TextUtils.isEmpty(appPreferences.getProxyPassword())) {
httpClient.proxyAuthenticator(new MagicAuthenticator(Credentials.basic(
appPreferences.getProxyUsername(),
appPreferences.getProxyPassword()), "Proxy-Authorization"));
}
while ((countedResponse = countedResponse.priorResponse()) != null) {
attemptsCount++;
if (attemptsCount == 3) {
return null;
}
}
httpClient.addInterceptor(new HeadersInterceptor());
return response.request().newBuilder()
.header(authenticatorType, credentials)
.build();
}
}
if (BuildConfig.DEBUG && !context.getResources().getBoolean(R.bool.nc_is_debug)) {
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
loggingInterceptor.redactHeader("Authorization");
loggingInterceptor.redactHeader("Proxy-Authorization");
httpClient.addInterceptor(loggingInterceptor);
} else if (context.getResources().getBoolean(R.bool.nc_is_debug)) {
private class GetProxyRunnable implements Runnable {
private volatile Proxy proxy;
private AppPreferences appPreferences;
HttpLoggingInterceptor.Logger fileLogger =
s -> LoggingUtils.INSTANCE.writeLogEntryToFile(context, s);
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(fileLogger);
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
loggingInterceptor.redactHeader("Authorization");
loggingInterceptor.redactHeader("Proxy-Authorization");
httpClient.addInterceptor(loggingInterceptor);
}
return httpClient.build();
GetProxyRunnable(AppPreferences appPreferences) {
this.appPreferences = appPreferences;
}
public static class HeadersInterceptor implements Interceptor {
@NonNull
@Override
public Response intercept(@NonNull Chain chain) throws IOException {
Request original = chain.request();
Request request = original.newBuilder()
.header("User-Agent", ApiUtils.getUserAgent())
.header("Accept", "application/json")
.header("OCS-APIRequest", "true")
.method(original.method(), original.body())
.build();
Response response = chain.proceed(request);
if (request.url().encodedPath().contains("/avatar/")) {
AvatarStatusCodeHolder.getInstance().setStatusCode(response.code());
}
return response;
}
@Override
public void run() {
if (Proxy.Type.SOCKS.equals(Proxy.Type.valueOf(appPreferences.getProxyType()))) {
proxy = new Proxy(Proxy.Type.valueOf(appPreferences.getProxyType()),
InetSocketAddress.createUnresolved(appPreferences.getProxyHost(), Integer.parseInt(
appPreferences.getProxyPort())));
} else {
proxy = new Proxy(Proxy.Type.valueOf(appPreferences.getProxyType()),
new InetSocketAddress(appPreferences.getProxyHost(),
Integer.parseInt(appPreferences.getProxyPort())));
}
}
public static class MagicAuthenticator implements Authenticator {
private String credentials;
private String authenticatorType;
public MagicAuthenticator(@NonNull String credentials, @NonNull String authenticatorType) {
this.credentials = credentials;
this.authenticatorType = authenticatorType;
}
@Nullable
@Override
public Request authenticate(@Nullable Route route, @NonNull Response response) {
if (response.request().header(authenticatorType) != null) {
return null;
}
Response countedResponse = response;
int attemptsCount = 0;
while ((countedResponse = countedResponse.priorResponse()) != null) {
attemptsCount++;
if (attemptsCount == 3) {
return null;
}
}
return response.request().newBuilder()
.header(authenticatorType, credentials)
.build();
}
}
private class GetProxyRunnable implements Runnable {
private volatile Proxy proxy;
private AppPreferences appPreferences;
GetProxyRunnable(AppPreferences appPreferences) {
this.appPreferences = appPreferences;
}
@Override
public void run() {
if (Proxy.Type.SOCKS.equals(Proxy.Type.valueOf(appPreferences.getProxyType()))) {
proxy = new Proxy(Proxy.Type.valueOf(appPreferences.getProxyType()),
InetSocketAddress.createUnresolved(appPreferences.getProxyHost(), Integer.parseInt(
appPreferences.getProxyPort())));
} else {
proxy = new Proxy(Proxy.Type.valueOf(appPreferences.getProxyType()),
new InetSocketAddress(appPreferences.getProxyHost(),
Integer.parseInt(appPreferences.getProxyPort())));
}
}
Proxy getProxyValue() {
return proxy;
}
Proxy getProxyValue() {
return proxy;
}
}
}

View File

@ -24,27 +24,28 @@ import lombok.Data;
@Data
public class BottomSheetLockEvent {
private final boolean cancelable;
private final int delay;
private final boolean shouldRefreshData;
private final boolean cancel;
private boolean dismissView;
private final boolean cancelable;
private final int delay;
private final boolean shouldRefreshData;
private final boolean cancel;
private boolean dismissView;
public BottomSheetLockEvent(boolean cancelable, int delay, boolean shouldRefreshData, boolean cancel) {
this.cancelable = cancelable;
this.delay = delay;
this.shouldRefreshData = shouldRefreshData;
this.cancel = cancel;
this.dismissView = true;
}
public BottomSheetLockEvent(boolean cancelable, int delay, boolean shouldRefreshData, boolean cancel, boolean
dismissView) {
this.cancelable = cancelable;
this.delay = delay;
this.shouldRefreshData = shouldRefreshData;
this.cancel = cancel;
this.dismissView = dismissView;
}
public BottomSheetLockEvent(boolean cancelable, int delay, boolean shouldRefreshData,
boolean cancel) {
this.cancelable = cancelable;
this.delay = delay;
this.shouldRefreshData = shouldRefreshData;
this.cancel = cancel;
this.dismissView = true;
}
public BottomSheetLockEvent(boolean cancelable, int delay, boolean shouldRefreshData,
boolean cancel, boolean
dismissView) {
this.cancelable = cancelable;
this.delay = delay;
this.shouldRefreshData = shouldRefreshData;
this.cancel = cancel;
this.dismissView = dismissView;
}
}

View File

@ -26,28 +26,28 @@ import com.nextcloud.talk.utils.ssl.MagicTrustManager;
import java.security.cert.X509Certificate;
public class CertificateEvent {
private final X509Certificate x509Certificate;
private final MagicTrustManager magicTrustManager;
@Nullable
private final SslErrorHandler sslErrorHandler;
private final X509Certificate x509Certificate;
private final MagicTrustManager magicTrustManager;
@Nullable
private final SslErrorHandler sslErrorHandler;
public CertificateEvent(X509Certificate x509Certificate, MagicTrustManager magicTrustManager,
@Nullable SslErrorHandler sslErrorHandler) {
this.x509Certificate = x509Certificate;
this.magicTrustManager = magicTrustManager;
this.sslErrorHandler = sslErrorHandler;
}
public CertificateEvent(X509Certificate x509Certificate, MagicTrustManager magicTrustManager,
@Nullable SslErrorHandler sslErrorHandler) {
this.x509Certificate = x509Certificate;
this.magicTrustManager = magicTrustManager;
this.sslErrorHandler = sslErrorHandler;
}
@Nullable
public SslErrorHandler getSslErrorHandler() {
return sslErrorHandler;
}
@Nullable
public SslErrorHandler getSslErrorHandler() {
return sslErrorHandler;
}
public X509Certificate getX509Certificate() {
return x509Certificate;
}
public X509Certificate getX509Certificate() {
return x509Certificate;
}
public MagicTrustManager getMagicTrustManager() {
return magicTrustManager;
}
public MagicTrustManager getMagicTrustManager() {
return magicTrustManager;
}
}

View File

@ -24,18 +24,17 @@ import lombok.Data;
@Data
public class EventStatus {
private long userId;
private EventType eventType;
private boolean allGood;
private long userId;
private EventType eventType;
private boolean allGood;
public EventStatus(long userId, EventType eventType, boolean allGood) {
this.userId = userId;
this.eventType = eventType;
this.allGood = allGood;
}
public enum EventType {
PUSH_REGISTRATION, CAPABILITIES_FETCH, SIGNALING_SETTINGS, CONVERSATION_UPDATE, PARTICIPANTS_UPDATE
}
public EventStatus(long userId, EventType eventType, boolean allGood) {
this.userId = userId;
this.eventType = eventType;
this.allGood = allGood;
}
public enum EventType {
PUSH_REGISTRATION, CAPABILITIES_FETCH, SIGNALING_SETTINGS, CONVERSATION_UPDATE, PARTICIPANTS_UPDATE
}
}

View File

@ -26,13 +26,14 @@ import org.webrtc.MediaStream;
@Data
public class MediaStreamEvent {
private final MediaStream mediaStream;
private final String session;
private final String videoStreamType;
private final MediaStream mediaStream;
private final String session;
private final String videoStreamType;
public MediaStreamEvent(@Nullable MediaStream mediaStream, String session, String videoStreamType) {
this.mediaStream = mediaStream;
this.session = session;
this.videoStreamType = videoStreamType;
}
public MediaStreamEvent(@Nullable MediaStream mediaStream, String session,
String videoStreamType) {
this.mediaStream = mediaStream;
this.session = session;
this.videoStreamType = videoStreamType;
}
}

View File

@ -25,9 +25,9 @@ import lombok.Data;
@Data
public class MoreMenuClickEvent {
private final Conversation conversation;
private final Conversation conversation;
public MoreMenuClickEvent(Conversation conversation) {
this.conversation = conversation;
}
public MoreMenuClickEvent(Conversation conversation) {
this.conversation = conversation;
}
}

View File

@ -24,13 +24,13 @@ import lombok.Data;
@Data
public class NetworkEvent {
public enum NetworkConnectionEvent {
NETWORK_CONNECTED, NETWORK_DISCONNECTED
}
private final NetworkConnectionEvent networkConnectionEvent;
private final NetworkConnectionEvent networkConnectionEvent;
public NetworkEvent(NetworkConnectionEvent networkConnectionEvent) {
this.networkConnectionEvent = networkConnectionEvent;
}
public NetworkEvent(NetworkConnectionEvent networkConnectionEvent) {
this.networkConnectionEvent = networkConnectionEvent;
}
public enum NetworkConnectionEvent {
NETWORK_CONNECTED, NETWORK_DISCONNECTED
}
}

View File

@ -25,22 +25,23 @@ import lombok.Data;
@Data
public class PeerConnectionEvent {
private final PeerConnectionEventType peerConnectionEventType;
private final String sessionId;
private final String nick;
private final Boolean changeValue;
private final String videoStreamType;
private final PeerConnectionEventType peerConnectionEventType;
private final String sessionId;
private final String nick;
private final Boolean changeValue;
private final String videoStreamType;
public PeerConnectionEvent(PeerConnectionEventType peerConnectionEventType, @Nullable String sessionId,
@Nullable String nick, Boolean changeValue, @Nullable String videoStreamType) {
this.peerConnectionEventType = peerConnectionEventType;
this.nick = nick;
this.changeValue = changeValue;
this.sessionId = sessionId;
this.videoStreamType = videoStreamType;
}
public PeerConnectionEvent(PeerConnectionEventType peerConnectionEventType,
@Nullable String sessionId,
@Nullable String nick, Boolean changeValue, @Nullable String videoStreamType) {
this.peerConnectionEventType = peerConnectionEventType;
this.nick = nick;
this.changeValue = changeValue;
this.sessionId = sessionId;
this.videoStreamType = videoStreamType;
}
public enum PeerConnectionEventType {
PEER_CONNECTED, PEER_CLOSED, SENSOR_FAR, SENSOR_NEAR, NICK_CHANGE, AUDIO_CHANGE, VIDEO_CHANGE, PUBLISHER_FAILED
}
public enum PeerConnectionEventType {
PEER_CONNECTED, PEER_CLOSED, SENSOR_FAR, SENSOR_NEAR, NICK_CHANGE, AUDIO_CHANGE, VIDEO_CHANGE, PUBLISHER_FAILED
}
}

View File

@ -27,20 +27,21 @@ import org.webrtc.SessionDescription;
@Data
public class SessionDescriptionSendEvent {
@Nullable
private final SessionDescription sessionDescription;
private final String peerId;
private final String type;
@Nullable
private final NCIceCandidate ncIceCandidate;
private final String videoStreamType;
@Nullable
private final SessionDescription sessionDescription;
private final String peerId;
private final String type;
@Nullable
private final NCIceCandidate ncIceCandidate;
private final String videoStreamType;
public SessionDescriptionSendEvent(@Nullable SessionDescription sessionDescription, String peerId, String type,
@Nullable NCIceCandidate ncIceCandidate, @Nullable String videoStreamType) {
this.sessionDescription = sessionDescription;
this.peerId = peerId;
this.type = type;
this.ncIceCandidate = ncIceCandidate;
this.videoStreamType = videoStreamType;
}
public SessionDescriptionSendEvent(@Nullable SessionDescription sessionDescription, String peerId,
String type,
@Nullable NCIceCandidate ncIceCandidate, @Nullable String videoStreamType) {
this.sessionDescription = sessionDescription;
this.peerId = peerId;
this.type = type;
this.ncIceCandidate = ncIceCandidate;
this.videoStreamType = videoStreamType;
}
}

View File

@ -24,5 +24,5 @@ import lombok.Data;
@Data
public class UserMentionClickEvent {
public final String userId;
public final String userId;
}

View File

@ -26,7 +26,7 @@ import lombok.Data;
@Data
public class WebSocketCommunicationEvent {
public final String type;
@Nullable
public final HashMap<String, String> hashMap;
public final String type;
@Nullable
public final HashMap<String, String> hashMap;
}

View File

@ -22,6 +22,6 @@ package com.nextcloud.talk.interfaces
interface ClosedInterface {
val isGooglePlayServicesAvailable: Boolean
fun providerInstallerInstallIfNeededAsync()
val isGooglePlayServicesAvailable: Boolean
fun providerInstallerInstallIfNeededAsync()
}

View File

@ -23,5 +23,8 @@ package com.nextcloud.talk.interfaces
import android.os.Bundle
interface ConversationMenuInterface {
fun openLovelyDialogWithIdAndBundle(dialogId: Int, bundle: Bundle)
fun openLovelyDialogWithIdAndBundle(
dialogId: Int,
bundle: Bundle
)
}

View File

@ -21,7 +21,7 @@
package com.nextcloud.talk.interfaces
interface SelectionInterface {
fun toggleBrowserItemSelection(path: String)
fun toggleBrowserItemSelection(path: String)
fun isPathSelected(path: String): Boolean
fun isPathSelected(path: String): Boolean
}

View File

@ -30,12 +30,12 @@ import androidx.work.Worker;
import androidx.work.WorkerParameters;
import autodagger.AutoInjector;
import com.bluelinelabs.logansquare.LoganSquare;
import com.nextcloud.talk.models.json.generic.GenericOverall;
import com.nextcloud.talk.models.json.push.PushConfigurationState;
import com.nextcloud.talk.R;
import com.nextcloud.talk.api.NcApi;
import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.models.database.UserEntity;
import com.nextcloud.talk.models.json.generic.GenericOverall;
import com.nextcloud.talk.models.json.push.PushConfigurationState;
import com.nextcloud.talk.utils.ApiUtils;
import com.nextcloud.talk.utils.database.arbitrarystorage.ArbitraryStorageUtils;
import com.nextcloud.talk.utils.database.user.UserUtils;
@ -54,196 +54,205 @@ import retrofit2.Retrofit;
@AutoInjector(NextcloudTalkApplication.class)
public class AccountRemovalWorker extends Worker {
public static final String TAG = "AccountRemovalWorker";
public static final String TAG = "AccountRemovalWorker";
@Inject
UserUtils userUtils;
@Inject
UserUtils userUtils;
@Inject
ArbitraryStorageUtils arbitraryStorageUtils;
@Inject
ArbitraryStorageUtils arbitraryStorageUtils;
@Inject
Retrofit retrofit;
@Inject
Retrofit retrofit;
@Inject
OkHttpClient okHttpClient;
@Inject
OkHttpClient okHttpClient;
NcApi ncApi;
NcApi ncApi;
public AccountRemovalWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
public AccountRemovalWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
@NonNull
@Override
public Result doWork() {
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
@NonNull
@Override
public Result doWork() {
NextcloudTalkApplication.Companion.getSharedApplication()
.getComponentApplication()
.inject(this);
PushConfigurationState pushConfigurationState;
String credentials;
for (Object userEntityObject : userUtils.getUsersScheduledForDeletion()) {
UserEntity userEntity = (UserEntity) userEntityObject;
try {
if (!TextUtils.isEmpty(userEntity.getPushConfigurationState())) {
pushConfigurationState = LoganSquare.parse(userEntity.getPushConfigurationState(),
PushConfigurationState.class);
PushConfigurationState finalPushConfigurationState = pushConfigurationState;
PushConfigurationState pushConfigurationState;
String credentials;
for (Object userEntityObject : userUtils.getUsersScheduledForDeletion()) {
UserEntity userEntity = (UserEntity) userEntityObject;
try {
if (!TextUtils.isEmpty(userEntity.getPushConfigurationState())) {
pushConfigurationState = LoganSquare.parse(userEntity.getPushConfigurationState(),
PushConfigurationState.class);
PushConfigurationState finalPushConfigurationState = pushConfigurationState;
credentials = ApiUtils.getCredentials(userEntity.getUsername(), userEntity.getToken());
credentials = ApiUtils.getCredentials(userEntity.getUsername(), userEntity.getToken());
ncApi = retrofit.newBuilder().client(okHttpClient.newBuilder().cookieJar(new
JavaNetCookieJar(new CookieManager())).build()).build().create(NcApi.class);
ncApi = retrofit.newBuilder().client(okHttpClient.newBuilder().cookieJar(new
JavaNetCookieJar(new CookieManager())).build()).build().create(NcApi.class);
String finalCredentials = credentials;
ncApi.unregisterDeviceForNotificationsWithNextcloud(credentials, ApiUtils.getUrlNextcloudPush(userEntity
.getBaseUrl()))
.blockingSubscribe(new Observer<GenericOverall>() {
@Override
public void onSubscribe(Disposable d) {
String finalCredentials = credentials;
ncApi.unregisterDeviceForNotificationsWithNextcloud(credentials,
ApiUtils.getUrlNextcloudPush(userEntity
.getBaseUrl()))
.blockingSubscribe(new Observer<GenericOverall>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(GenericOverall genericOverall) {
if (genericOverall.getOcs().getMeta().getStatusCode() == 200
|| genericOverall.getOcs().getMeta().getStatusCode() == 202) {
HashMap<String, String> queryMap = new HashMap<>();
queryMap.put("deviceIdentifier", finalPushConfigurationState.getDeviceIdentifier());
queryMap.put("userPublicKey", finalPushConfigurationState.getUserPublicKey());
queryMap.put("deviceIdentifierSignature",
finalPushConfigurationState.getDeviceIdentifierSignature());
ncApi.unregisterDeviceForNotificationsWithProxy
(ApiUtils.getUrlPushProxy(), queryMap)
.subscribe(new Observer<Void>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Void aVoid) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String groupName = String.format(getApplicationContext().getResources()
.getString(R.string
.nc_notification_channel), userEntity.getUserId(), userEntity.getBaseUrl());
CRC32 crc32 = new CRC32();
crc32.update(groupName.getBytes());
NotificationManager notificationManager =
(NotificationManager) getApplicationContext().getSystemService
(Context.NOTIFICATION_SERVICE);
if (notificationManager != null) {
notificationManager.deleteNotificationChannelGroup(Long
.toString(crc32.getValue()));
}
}
WebSocketConnectionHelper.deleteExternalSignalingInstanceForUserEntity(userEntity.getId());
arbitraryStorageUtils.deleteAllEntriesForAccountIdentifier(userEntity.getId()).subscribe(new Observer() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Object o) {
userUtils.deleteUser(userEntity.getId()).subscribe(new CompletableObserver() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onComplete() {
}
@Override
public void onError(Throwable e) {
}
});
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
} else {
userUtils.deleteUser(userEntity.getId())
.subscribe(new CompletableObserver() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onComplete() {
}
@Override
public void onError(Throwable e) {
}
});
}
} catch (IOException e) {
Log.d(TAG, "Something went wrong while removing job at parsing PushConfigurationState");
userUtils.deleteUser(userEntity.getId())
.subscribe(new CompletableObserver() {
@Override
public void onSubscribe(Disposable d) {
@Override
public void onNext(GenericOverall genericOverall) {
if (genericOverall.getOcs().getMeta().getStatusCode() == 200
|| genericOverall.getOcs().getMeta().getStatusCode() == 202) {
HashMap<String, String> queryMap = new HashMap<>();
queryMap.put("deviceIdentifier",
finalPushConfigurationState.getDeviceIdentifier());
queryMap.put("userPublicKey", finalPushConfigurationState.getUserPublicKey());
queryMap.put("deviceIdentifierSignature",
finalPushConfigurationState.getDeviceIdentifierSignature());
ncApi.unregisterDeviceForNotificationsWithProxy
(ApiUtils.getUrlPushProxy(), queryMap)
.subscribe(new Observer<Void>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Void aVoid) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String groupName =
String.format(getApplicationContext().getResources()
.getString(R.string
.nc_notification_channel), userEntity.getUserId(),
userEntity.getBaseUrl());
CRC32 crc32 = new CRC32();
crc32.update(groupName.getBytes());
NotificationManager notificationManager =
(NotificationManager) getApplicationContext().getSystemService
(Context.NOTIFICATION_SERVICE);
if (notificationManager != null) {
notificationManager.deleteNotificationChannelGroup(Long
.toString(crc32.getValue()));
}
}
@Override
public void onComplete() {
WebSocketConnectionHelper.deleteExternalSignalingInstanceForUserEntity(
userEntity.getId());
}
arbitraryStorageUtils.deleteAllEntriesForAccountIdentifier(
userEntity.getId()).subscribe(new Observer() {
@Override
public void onSubscribe(Disposable d) {
@Override
public void onError(Throwable e) {
}
}
@Override
public void onNext(Object o) {
userUtils.deleteUser(userEntity.getId())
.subscribe(new CompletableObserver() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onComplete() {
}
@Override
public void onError(Throwable e) {
}
});
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
}
}
}
return Result.success();
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
} else {
userUtils.deleteUser(userEntity.getId())
.subscribe(new CompletableObserver() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onComplete() {
}
@Override
public void onError(Throwable e) {
}
});
}
} catch (IOException e) {
Log.d(TAG, "Something went wrong while removing job at parsing PushConfigurationState");
userUtils.deleteUser(userEntity.getId())
.subscribe(new CompletableObserver() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onComplete() {
}
@Override
public void onError(Throwable e) {
}
});
}
}
return Result.success();
}
}

View File

@ -26,10 +26,10 @@ import androidx.work.Data;
import androidx.work.Worker;
import androidx.work.WorkerParameters;
import autodagger.AutoInjector;
import com.nextcloud.talk.models.RetrofitBucket;
import com.nextcloud.talk.api.NcApi;
import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.events.EventStatus;
import com.nextcloud.talk.models.RetrofitBucket;
import com.nextcloud.talk.models.database.UserEntity;
import com.nextcloud.talk.utils.ApiUtils;
import com.nextcloud.talk.utils.bundle.BundleKeys;
@ -40,50 +40,56 @@ import org.greenrobot.eventbus.EventBus;
@AutoInjector(NextcloudTalkApplication.class)
public class AddParticipantsToConversation extends Worker {
@Inject
NcApi ncApi;
@Inject
NcApi ncApi;
@Inject
UserUtils userUtils;
@Inject
UserUtils userUtils;
@Inject
EventBus eventBus;
@Inject
EventBus eventBus;
public AddParticipantsToConversation(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
public AddParticipantsToConversation(@NonNull Context context,
@NonNull WorkerParameters workerParams) {
super(context, workerParams);
NextcloudTalkApplication.Companion.getSharedApplication()
.getComponentApplication()
.inject(this);
}
@NonNull
@Override
public Result doWork() {
Data data = getInputData();
String[] selectedUserIds = data.getStringArray(BundleKeys.INSTANCE.getKEY_SELECTED_USERS());
String[] selectedGroupIds = data.getStringArray(BundleKeys.INSTANCE.getKEY_SELECTED_GROUPS());
UserEntity user = userUtils.getUserWithInternalId(
data.getLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), -1));
String conversationToken = data.getString(BundleKeys.INSTANCE.getKEY_TOKEN());
String credentials = ApiUtils.getCredentials(user.getUsername(), user.getToken());
RetrofitBucket retrofitBucket;
for (String userId : selectedUserIds) {
retrofitBucket =
ApiUtils.getRetrofitBucketForAddParticipant(user.getBaseUrl(), conversationToken,
userId);
ncApi.addParticipant(credentials, retrofitBucket.getUrl(), retrofitBucket.getQueryMap())
.subscribeOn(Schedulers.io())
.blockingSubscribe();
}
@NonNull
@Override
public Result doWork() {
Data data = getInputData();
String[] selectedUserIds = data.getStringArray(BundleKeys.INSTANCE.getKEY_SELECTED_USERS());
String[] selectedGroupIds = data.getStringArray(BundleKeys.INSTANCE.getKEY_SELECTED_GROUPS());
UserEntity user = userUtils.getUserWithInternalId(data.getLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), -1));
String conversationToken = data.getString(BundleKeys.INSTANCE.getKEY_TOKEN());
String credentials = ApiUtils.getCredentials(user.getUsername(), user.getToken());
for (String groupId : selectedGroupIds) {
retrofitBucket =
ApiUtils.getRetrofitBucketForAddGroupParticipant(user.getBaseUrl(), conversationToken,
groupId);
RetrofitBucket retrofitBucket;
for (String userId : selectedUserIds) {
retrofitBucket = ApiUtils.getRetrofitBucketForAddParticipant(user.getBaseUrl(), conversationToken,
userId);
ncApi.addParticipant(credentials, retrofitBucket.getUrl(), retrofitBucket.getQueryMap())
.subscribeOn(Schedulers.io())
.blockingSubscribe();
}
for (String groupId : selectedGroupIds) {
retrofitBucket = ApiUtils.getRetrofitBucketForAddGroupParticipant(user.getBaseUrl(), conversationToken,
groupId);
ncApi.addParticipant(credentials, retrofitBucket.getUrl(), retrofitBucket.getQueryMap())
.subscribeOn(Schedulers.io())
.blockingSubscribe();
}
eventBus.post(new EventStatus(user.getId(), EventStatus.EventType.PARTICIPANTS_UPDATE, true));
return Result.success();
ncApi.addParticipant(credentials, retrofitBucket.getUrl(), retrofitBucket.getQueryMap())
.subscribeOn(Schedulers.io())
.blockingSubscribe();
}
eventBus.post(new EventStatus(user.getId(), EventStatus.EventType.PARTICIPANTS_UPDATE, true));
return Result.success();
}
}

View File

@ -28,11 +28,11 @@ import androidx.work.Worker;
import androidx.work.WorkerParameters;
import autodagger.AutoInjector;
import com.bluelinelabs.logansquare.LoganSquare;
import com.nextcloud.talk.models.json.capabilities.CapabilitiesOverall;
import com.nextcloud.talk.api.NcApi;
import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.events.EventStatus;
import com.nextcloud.talk.models.database.UserEntity;
import com.nextcloud.talk.models.json.capabilities.CapabilitiesOverall;
import com.nextcloud.talk.utils.ApiUtils;
import com.nextcloud.talk.utils.bundle.BundleKeys;
import com.nextcloud.talk.utils.database.user.UserUtils;
@ -50,114 +50,116 @@ import retrofit2.Retrofit;
@AutoInjector(NextcloudTalkApplication.class)
public class CapabilitiesWorker extends Worker {
public static final String TAG = "CapabilitiesWorker";
public static final String TAG = "CapabilitiesWorker";
@Inject
UserUtils userUtils;
@Inject
UserUtils userUtils;
@Inject
Retrofit retrofit;
@Inject
Retrofit retrofit;
@Inject
EventBus eventBus;
@Inject
EventBus eventBus;
@Inject
OkHttpClient okHttpClient;
@Inject
OkHttpClient okHttpClient;
NcApi ncApi;
NcApi ncApi;
public CapabilitiesWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
public CapabilitiesWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
private void updateUser(CapabilitiesOverall capabilitiesOverall, UserEntity internalUserEntity) {
try {
userUtils.createOrUpdateUser(null, null,
null, null,
null, null, null, internalUserEntity.getId(),
LoganSquare.serialize(capabilitiesOverall.getOcs().getData().getCapabilities()), null,
null)
.blockingSubscribe(new Observer<UserEntity>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(UserEntity userEntity) {
eventBus.post(new EventStatus(userEntity.getId(),
EventStatus.EventType.CAPABILITIES_FETCH, true));
}
@Override
public void onError(Throwable e) {
eventBus.post(new EventStatus(internalUserEntity.getId(),
EventStatus.EventType.CAPABILITIES_FETCH, false));
}
@Override
public void onComplete() {
}
});
} catch (IOException e) {
Log.e(TAG, "Failed to create or update user");
}
}
@NonNull
@Override
public Result doWork() {
NextcloudTalkApplication.Companion.getSharedApplication()
.getComponentApplication()
.inject(this);
Data data = getInputData();
long internalUserId = data.getLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), -1);
UserEntity userEntity;
List userEntityObjectList = new ArrayList();
if (internalUserId == -1
|| (userEntity = userUtils.getUserWithInternalId(internalUserId)) == null) {
userEntityObjectList = userUtils.getUsers();
} else {
userEntityObjectList.add(userEntity);
}
private void updateUser(CapabilitiesOverall capabilitiesOverall, UserEntity internalUserEntity) {
try {
userUtils.createOrUpdateUser(null, null,
null, null,
null, null, null, internalUserEntity.getId(),
LoganSquare.serialize(capabilitiesOverall.getOcs().getData().getCapabilities()), null, null)
.blockingSubscribe(new Observer<UserEntity>() {
@Override
public void onSubscribe(Disposable d) {
for (Object userEntityObject : userEntityObjectList) {
UserEntity internalUserEntity = (UserEntity) userEntityObject;
}
ncApi = retrofit.newBuilder().client(okHttpClient.newBuilder().cookieJar(new
JavaNetCookieJar(new CookieManager())).build()).build().create(NcApi.class);
@Override
public void onNext(UserEntity userEntity) {
eventBus.post(new EventStatus(userEntity.getId(),
EventStatus.EventType.CAPABILITIES_FETCH, true));
}
ncApi.getCapabilities(ApiUtils.getCredentials(internalUserEntity.getUsername(),
internalUserEntity.getToken()),
ApiUtils.getUrlForCapabilities(internalUserEntity.getBaseUrl()))
.retry(3)
.blockingSubscribe(new Observer<CapabilitiesOverall>() {
@Override
public void onSubscribe(Disposable d) {
@Override
public void onError(Throwable e) {
eventBus.post(new EventStatus(internalUserEntity.getId(),
EventStatus.EventType.CAPABILITIES_FETCH, false));
}
}
@Override
public void onComplete() {
@Override
public void onNext(CapabilitiesOverall capabilitiesOverall) {
updateUser(capabilitiesOverall, internalUserEntity);
}
}
});
} catch (IOException e) {
Log.e(TAG, "Failed to create or update user");
}
@Override
public void onError(Throwable e) {
eventBus.post(new EventStatus(internalUserEntity.getId(),
EventStatus.EventType.CAPABILITIES_FETCH, false));
}
@Override
public void onComplete() {
}
});
}
@NonNull
@Override
public Result doWork() {
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
Data data = getInputData();
long internalUserId = data.getLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), -1);
UserEntity userEntity;
List userEntityObjectList = new ArrayList();
if (internalUserId == -1 || (userEntity = userUtils.getUserWithInternalId(internalUserId)) == null) {
userEntityObjectList = userUtils.getUsers();
} else {
userEntityObjectList.add(userEntity);
}
for (Object userEntityObject : userEntityObjectList) {
UserEntity internalUserEntity = (UserEntity) userEntityObject;
ncApi = retrofit.newBuilder().client(okHttpClient.newBuilder().cookieJar(new
JavaNetCookieJar(new CookieManager())).build()).build().create(NcApi.class);
ncApi.getCapabilities(ApiUtils.getCredentials(internalUserEntity.getUsername(),
internalUserEntity.getToken()), ApiUtils.getUrlForCapabilities(internalUserEntity.getBaseUrl()))
.retry(3)
.blockingSubscribe(new Observer<CapabilitiesOverall>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(CapabilitiesOverall capabilitiesOverall) {
updateUser(capabilitiesOverall, internalUserEntity);
}
@Override
public void onError(Throwable e) {
eventBus.post(new EventStatus(internalUserEntity.getId(),
EventStatus.EventType.CAPABILITIES_FETCH, false));
}
@Override
public void onComplete() {
}
});
}
return Result.success();
}
return Result.success();
}
}

View File

@ -26,11 +26,11 @@ import androidx.work.Data;
import androidx.work.Worker;
import androidx.work.WorkerParameters;
import autodagger.AutoInjector;
import com.nextcloud.talk.models.json.generic.GenericOverall;
import com.nextcloud.talk.api.NcApi;
import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.events.EventStatus;
import com.nextcloud.talk.models.database.UserEntity;
import com.nextcloud.talk.models.json.generic.GenericOverall;
import com.nextcloud.talk.utils.ApiUtils;
import com.nextcloud.talk.utils.bundle.BundleKeys;
import com.nextcloud.talk.utils.database.user.UserUtils;
@ -46,70 +46,72 @@ import retrofit2.Retrofit;
@AutoInjector(NextcloudTalkApplication.class)
public class DeleteConversationWorker extends Worker {
@Inject
Retrofit retrofit;
@Inject
Retrofit retrofit;
@Inject
OkHttpClient okHttpClient;
@Inject
OkHttpClient okHttpClient;
@Inject
UserUtils userUtils;
@Inject
UserUtils userUtils;
@Inject
EventBus eventBus;
@Inject
EventBus eventBus;
NcApi ncApi;
NcApi ncApi;
public DeleteConversationWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
public DeleteConversationWorker(@NonNull Context context,
@NonNull WorkerParameters workerParams) {
super(context, workerParams);
NextcloudTalkApplication.Companion.getSharedApplication()
.getComponentApplication()
.inject(this);
}
@NonNull
@Override
public Result doWork() {
Data data = getInputData();
long operationUserId = data.getLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), -1);
String conversationToken = data.getString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN());
UserEntity operationUser = userUtils.getUserWithId(operationUserId);
if (operationUser != null) {
String credentials =
ApiUtils.getCredentials(operationUser.getUsername(), operationUser.getToken());
ncApi = retrofit.newBuilder().client(okHttpClient.newBuilder().cookieJar(new
JavaNetCookieJar(new CookieManager())).build()).build().create(NcApi.class);
EventStatus eventStatus = new EventStatus(operationUser.getId(),
EventStatus.EventType.CONVERSATION_UPDATE, true);
ncApi.deleteRoom(credentials, ApiUtils.getRoom(operationUser.getBaseUrl(), conversationToken))
.subscribeOn(Schedulers.io())
.blockingSubscribe(new Observer<GenericOverall>() {
Disposable disposable;
@Override
public void onSubscribe(Disposable d) {
disposable = d;
}
@Override
public void onNext(GenericOverall genericOverall) {
eventBus.postSticky(eventStatus);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
disposable.dispose();
}
});
}
@NonNull
@Override
public Result doWork() {
Data data = getInputData();
long operationUserId = data.getLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), -1);
String conversationToken = data.getString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN());
UserEntity operationUser = userUtils.getUserWithId(operationUserId);
if (operationUser != null) {
String credentials = ApiUtils.getCredentials(operationUser.getUsername(), operationUser.getToken());
ncApi = retrofit.newBuilder().client(okHttpClient.newBuilder().cookieJar(new
JavaNetCookieJar(new CookieManager())).build()).build().create(NcApi.class);
EventStatus eventStatus = new EventStatus(operationUser.getId(),
EventStatus.EventType.CONVERSATION_UPDATE, true);
ncApi.deleteRoom(credentials, ApiUtils.getRoom(operationUser.getBaseUrl(), conversationToken))
.subscribeOn(Schedulers.io())
.blockingSubscribe(new Observer<GenericOverall>() {
Disposable disposable;
@Override
public void onSubscribe(Disposable d) {
disposable = d;
}
@Override
public void onNext(GenericOverall genericOverall) {
eventBus.postSticky(eventStatus);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
disposable.dispose();
}
});
}
return Result.success();
}
return Result.success();
}
}

View File

@ -26,11 +26,11 @@ import androidx.work.Data;
import androidx.work.Worker;
import androidx.work.WorkerParameters;
import autodagger.AutoInjector;
import com.nextcloud.talk.models.json.generic.GenericOverall;
import com.nextcloud.talk.api.NcApi;
import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.events.EventStatus;
import com.nextcloud.talk.models.database.UserEntity;
import com.nextcloud.talk.models.json.generic.GenericOverall;
import com.nextcloud.talk.utils.ApiUtils;
import com.nextcloud.talk.utils.bundle.BundleKeys;
import com.nextcloud.talk.utils.database.user.UserUtils;
@ -46,70 +46,72 @@ import retrofit2.Retrofit;
@AutoInjector(NextcloudTalkApplication.class)
public class LeaveConversationWorker extends Worker {
@Inject
Retrofit retrofit;
@Inject
Retrofit retrofit;
@Inject
OkHttpClient okHttpClient;
@Inject
OkHttpClient okHttpClient;
@Inject
UserUtils userUtils;
@Inject
UserUtils userUtils;
@Inject
EventBus eventBus;
@Inject
EventBus eventBus;
NcApi ncApi;
NcApi ncApi;
public LeaveConversationWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
public LeaveConversationWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
NextcloudTalkApplication.Companion.getSharedApplication()
.getComponentApplication()
.inject(this);
}
@NonNull
@Override
public Result doWork() {
Data data = getInputData();
long operationUserId = data.getLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), -1);
String conversationToken = data.getString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN());
UserEntity operationUser = userUtils.getUserWithId(operationUserId);
if (operationUser != null) {
String credentials =
ApiUtils.getCredentials(operationUser.getUsername(), operationUser.getToken());
ncApi = retrofit.newBuilder().client(okHttpClient.newBuilder().cookieJar(new
JavaNetCookieJar(new CookieManager())).build()).build().create(NcApi.class);
EventStatus eventStatus = new EventStatus(operationUser.getId(),
EventStatus.EventType.CONVERSATION_UPDATE, true);
ncApi.removeSelfFromRoom(credentials,
ApiUtils.getUrlForRemoveSelfFromRoom(operationUser.getBaseUrl(), conversationToken))
.subscribeOn(Schedulers.io())
.blockingSubscribe(new Observer<GenericOverall>() {
Disposable disposable;
@Override
public void onSubscribe(Disposable d) {
disposable = d;
}
@Override
public void onNext(GenericOverall genericOverall) {
eventBus.postSticky(eventStatus);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
disposable.dispose();
}
});
}
@NonNull
@Override
public Result doWork() {
Data data = getInputData();
long operationUserId = data.getLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), -1);
String conversationToken = data.getString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN());
UserEntity operationUser = userUtils.getUserWithId(operationUserId);
if (operationUser != null) {
String credentials = ApiUtils.getCredentials(operationUser.getUsername(), operationUser.getToken());
ncApi = retrofit.newBuilder().client(okHttpClient.newBuilder().cookieJar(new
JavaNetCookieJar(new CookieManager())).build()).build().create(NcApi.class);
EventStatus eventStatus = new EventStatus(operationUser.getId(),
EventStatus.EventType.CONVERSATION_UPDATE, true);
ncApi.removeSelfFromRoom(credentials, ApiUtils.getUrlForRemoveSelfFromRoom(operationUser.getBaseUrl(), conversationToken))
.subscribeOn(Schedulers.io())
.blockingSubscribe(new Observer<GenericOverall>() {
Disposable disposable;
@Override
public void onSubscribe(Disposable d) {
disposable = d;
}
@Override
public void onNext(GenericOverall genericOverall) {
eventBus.postSticky(eventStatus);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
disposable.dispose();
}
});
}
return Result.success();
}
return Result.success();
}
}

View File

@ -27,19 +27,19 @@ import androidx.work.WorkerParameters;
import com.nextcloud.talk.utils.PushUtils;
public class PushRegistrationWorker extends Worker {
public static final String TAG = "PushRegistrationWorker";
public static final String TAG = "PushRegistrationWorker";
public PushRegistrationWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
public PushRegistrationWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
@NonNull
@Override
public Result doWork() {
PushUtils pushUtils = new PushUtils();
pushUtils.generateRsa2048KeyPair();
pushUtils.pushRegistrationToServer();
@NonNull
@Override
public Result doWork() {
PushUtils pushUtils = new PushUtils();
pushUtils.generateRsa2048KeyPair();
pushUtils.pushRegistrationToServer();
return Result.success();
}
return Result.success();
}
}

View File

@ -42,63 +42,64 @@ import javax.inject.Inject;
@AutoInjector(NextcloudTalkApplication.class)
public class ShareOperationWorker extends Worker {
@Inject
UserUtils userUtils;
@Inject
NcApi ncApi;
private long userId;
private UserEntity operationsUser;
private String roomToken;
private List<String> filesArray = new ArrayList<>();
private String credentials;
private String baseUrl;
@Inject
UserUtils userUtils;
@Inject
NcApi ncApi;
private long userId;
private UserEntity operationsUser;
private String roomToken;
private List<String> filesArray = new ArrayList<>();
private String credentials;
private String baseUrl;
public ShareOperationWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
Data data = workerParams.getInputData();
userId = data.getLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), 0);
roomToken = data.getString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN());
Collections.addAll(filesArray, data.getStringArray(BundleKeys.INSTANCE.getKEY_FILE_PATHS()));
operationsUser = userUtils.getUserWithId(userId);
credentials = ApiUtils.getCredentials(operationsUser.getUsername(), operationsUser.getToken());
baseUrl = operationsUser.getBaseUrl();
public ShareOperationWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
NextcloudTalkApplication.Companion.getSharedApplication()
.getComponentApplication()
.inject(this);
Data data = workerParams.getInputData();
userId = data.getLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), 0);
roomToken = data.getString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN());
Collections.addAll(filesArray, data.getStringArray(BundleKeys.INSTANCE.getKEY_FILE_PATHS()));
operationsUser = userUtils.getUserWithId(userId);
credentials = ApiUtils.getCredentials(operationsUser.getUsername(), operationsUser.getToken());
baseUrl = operationsUser.getBaseUrl();
}
@NonNull
@Override
public Result doWork() {
for (int i = 0; i < filesArray.size(); i++) {
ncApi.createRemoteShare(credentials,
ApiUtils.getSharingUrl(baseUrl),
filesArray.get(i),
roomToken,
"10")
.subscribeOn(Schedulers.io())
.blockingSubscribe(new Observer<Void>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Void aVoid) {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
@NonNull
@Override
public Result doWork() {
for (int i = 0; i < filesArray.size(); i++) {
ncApi.createRemoteShare(credentials,
ApiUtils.getSharingUrl(baseUrl),
filesArray.get(i),
roomToken,
"10")
.subscribeOn(Schedulers.io())
.blockingSubscribe(new Observer<Void>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Void aVoid) {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
return Result.success();
}
return Result.success();
}
}

View File

@ -30,12 +30,12 @@ import androidx.work.Worker;
import androidx.work.WorkerParameters;
import autodagger.AutoInjector;
import com.bluelinelabs.logansquare.LoganSquare;
import com.nextcloud.talk.models.ExternalSignalingServer;
import com.nextcloud.talk.models.json.signaling.settings.SignalingSettingsOverall;
import com.nextcloud.talk.api.NcApi;
import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.events.EventStatus;
import com.nextcloud.talk.models.ExternalSignalingServer;
import com.nextcloud.talk.models.database.UserEntity;
import com.nextcloud.talk.models.json.signaling.settings.SignalingSettingsOverall;
import com.nextcloud.talk.utils.ApiUtils;
import com.nextcloud.talk.utils.bundle.BundleKeys;
import com.nextcloud.talk.utils.database.user.UserUtils;
@ -49,100 +49,112 @@ import org.greenrobot.eventbus.EventBus;
@AutoInjector(NextcloudTalkApplication.class)
public class SignalingSettingsWorker extends Worker {
private static final String TAG = "SignalingSettingsJob";
private static final String TAG = "SignalingSettingsJob";
@Inject
UserUtils userUtils;
@Inject
UserUtils userUtils;
@Inject
NcApi ncApi;
@Inject
NcApi ncApi;
@Inject
EventBus eventBus;
@Inject
EventBus eventBus;
public SignalingSettingsWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
public SignalingSettingsWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
@NonNull
@Override
public Result doWork() {
NextcloudTalkApplication.Companion.getSharedApplication()
.getComponentApplication()
.inject(this);
Data data = getInputData();
long internalUserId = data.getLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), -1);
List<UserEntity> userEntityList = new ArrayList<>();
UserEntity userEntity;
if (internalUserId == -1
|| (userEntity = userUtils.getUserWithInternalId(internalUserId)) == null) {
userEntityList = userUtils.getUsers();
} else {
userEntityList.add(userEntity);
}
@NonNull
@Override
public Result doWork() {
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
for (int i = 0; i < userEntityList.size(); i++) {
userEntity = userEntityList.get(i);
UserEntity finalUserEntity = userEntity;
ncApi.getSignalingSettings(
ApiUtils.getCredentials(userEntity.getUsername(), userEntity.getToken()),
ApiUtils.getUrlForSignalingSettings(userEntity.getBaseUrl()))
.blockingSubscribe(new Observer<SignalingSettingsOverall>() {
@Override
public void onSubscribe(Disposable d) {
Data data = getInputData();
}
long internalUserId = data.getLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), -1);
@Override
public void onNext(SignalingSettingsOverall signalingSettingsOverall) {
ExternalSignalingServer externalSignalingServer;
externalSignalingServer = new ExternalSignalingServer();
externalSignalingServer.setExternalSignalingServer(
signalingSettingsOverall.getOcs().getSettings().getExternalSignalingServer());
externalSignalingServer.setExternalSignalingTicket(
signalingSettingsOverall.getOcs().getSettings().getExternalSignalingTicket());
List<UserEntity> userEntityList = new ArrayList<>();
UserEntity userEntity;
if (internalUserId == -1 || (userEntity = userUtils.getUserWithInternalId(internalUserId)) == null) {
userEntityList = userUtils.getUsers();
} else {
userEntityList.add(userEntity);
}
try {
userUtils.createOrUpdateUser(null, null, null, null, null,
null, null, finalUserEntity.getId(), null, null,
LoganSquare.serialize(externalSignalingServer))
.subscribe(new Observer<UserEntity>() {
@Override
public void onSubscribe(Disposable d) {
for (int i = 0; i < userEntityList.size(); i++) {
userEntity = userEntityList.get(i);
UserEntity finalUserEntity = userEntity;
ncApi.getSignalingSettings(ApiUtils.getCredentials(userEntity.getUsername(), userEntity.getToken()),
ApiUtils.getUrlForSignalingSettings(userEntity.getBaseUrl()))
.blockingSubscribe(new Observer<SignalingSettingsOverall>() {
@Override
public void onSubscribe(Disposable d) {
}
}
@Override
public void onNext(UserEntity userEntity) {
eventBus.post(new EventStatus(finalUserEntity.getId(),
EventStatus.EventType.SIGNALING_SETTINGS, true));
}
@Override
public void onNext(SignalingSettingsOverall signalingSettingsOverall) {
ExternalSignalingServer externalSignalingServer;
externalSignalingServer = new ExternalSignalingServer();
externalSignalingServer.setExternalSignalingServer(signalingSettingsOverall.getOcs().getSettings().getExternalSignalingServer());
externalSignalingServer.setExternalSignalingTicket(signalingSettingsOverall.getOcs().getSettings().getExternalSignalingTicket());
@Override
public void onError(Throwable e) {
eventBus.post(new EventStatus(finalUserEntity.getId(),
EventStatus.EventType.SIGNALING_SETTINGS, false));
}
try {
userUtils.createOrUpdateUser(null, null, null, null, null,
null, null, finalUserEntity.getId(), null, null, LoganSquare.serialize(externalSignalingServer))
.subscribe(new Observer<UserEntity>() {
@Override
public void onSubscribe(Disposable d) {
@Override
public void onComplete() {
}
@Override
public void onNext(UserEntity userEntity) {
eventBus.post(new EventStatus(finalUserEntity.getId(), EventStatus.EventType.SIGNALING_SETTINGS, true));
}
@Override
public void onError(Throwable e) {
eventBus.post(new EventStatus(finalUserEntity.getId(), EventStatus.EventType.SIGNALING_SETTINGS, false));
}
@Override
public void onComplete() {
}
});
} catch (IOException e) {
Log.e(TAG, "Failed to serialize external signaling server");
}
}
@Override
public void onError(Throwable e) {
eventBus.post(new EventStatus(finalUserEntity.getId(), EventStatus.EventType.SIGNALING_SETTINGS, false));
}
@Override
public void onComplete() {
}
}
});
}
} catch (IOException e) {
Log.e(TAG, "Failed to serialize external signaling server");
}
}
OneTimeWorkRequest websocketConnectionsWorker = new OneTimeWorkRequest.Builder(WebsocketConnectionsWorker.class).build();
WorkManager.getInstance().enqueue(websocketConnectionsWorker);
@Override
public void onError(Throwable e) {
eventBus.post(
new EventStatus(finalUserEntity.getId(), EventStatus.EventType.SIGNALING_SETTINGS,
false));
}
return Result.success();
@Override
public void onComplete() {
}
});
}
OneTimeWorkRequest websocketConnectionsWorker =
new OneTimeWorkRequest.Builder(WebsocketConnectionsWorker.class).build();
WorkManager.getInstance().enqueue(websocketConnectionsWorker);
return Result.success();
}
}

View File

@ -29,8 +29,8 @@ import androidx.work.Worker;
import androidx.work.WorkerParameters;
import autodagger.AutoInjector;
import com.bluelinelabs.logansquare.LoganSquare;
import com.nextcloud.talk.models.ExternalSignalingServer;
import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.models.ExternalSignalingServer;
import com.nextcloud.talk.models.database.UserEntity;
import com.nextcloud.talk.utils.database.user.UserUtils;
import com.nextcloud.talk.webrtc.WebSocketConnectionHelper;
@ -41,43 +41,47 @@ import javax.inject.Inject;
@AutoInjector(NextcloudTalkApplication.class)
public class WebsocketConnectionsWorker extends Worker {
private static final String TAG = "WebsocketConnectionsWorker";
private static final String TAG = "WebsocketConnectionsWorker";
@Inject
UserUtils userUtils;
@Inject
UserUtils userUtils;
public WebsocketConnectionsWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
public WebsocketConnectionsWorker(@NonNull Context context,
@NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
@SuppressLint("LongLogTag")
@NonNull
@Override
public Result doWork() {
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
@SuppressLint("LongLogTag")
@NonNull
@Override
public Result doWork() {
NextcloudTalkApplication.Companion.getSharedApplication()
.getComponentApplication()
.inject(this);
List<UserEntity> userEntityList = userUtils.getUsers();
UserEntity userEntity;
ExternalSignalingServer externalSignalingServer;
WebSocketConnectionHelper webSocketConnectionHelper = new WebSocketConnectionHelper();
for (int i = 0; i < userEntityList.size(); i++) {
userEntity = userEntityList.get(i);
if (!TextUtils.isEmpty(userEntity.getExternalSignalingServer())) {
try {
externalSignalingServer = LoganSquare.parse(userEntity.getExternalSignalingServer(), ExternalSignalingServer.class);
if (!TextUtils.isEmpty(externalSignalingServer.getExternalSignalingServer()) &&
!TextUtils.isEmpty(externalSignalingServer.getExternalSignalingTicket())) {
WebSocketConnectionHelper.getExternalSignalingInstanceForServer(
externalSignalingServer.getExternalSignalingServer(),
userEntity, externalSignalingServer.getExternalSignalingTicket(),
false);
}
} catch (IOException e) {
Log.e(TAG, "Failed to parse external signaling server");
}
}
List<UserEntity> userEntityList = userUtils.getUsers();
UserEntity userEntity;
ExternalSignalingServer externalSignalingServer;
WebSocketConnectionHelper webSocketConnectionHelper = new WebSocketConnectionHelper();
for (int i = 0; i < userEntityList.size(); i++) {
userEntity = userEntityList.get(i);
if (!TextUtils.isEmpty(userEntity.getExternalSignalingServer())) {
try {
externalSignalingServer = LoganSquare.parse(userEntity.getExternalSignalingServer(),
ExternalSignalingServer.class);
if (!TextUtils.isEmpty(externalSignalingServer.getExternalSignalingServer()) &&
!TextUtils.isEmpty(externalSignalingServer.getExternalSignalingTicket())) {
WebSocketConnectionHelper.getExternalSignalingInstanceForServer(
externalSignalingServer.getExternalSignalingServer(),
userEntity, externalSignalingServer.getExternalSignalingTicket(),
false);
}
} catch (IOException e) {
Log.e(TAG, "Failed to parse external signaling server");
}
return Result.success();
}
}
return Result.success();
}
}

View File

@ -29,8 +29,8 @@ import org.parceler.Parcel;
@Parcel
@JsonObject
public class ExternalSignalingServer {
@JsonField(name = "externalSignalingServer")
String externalSignalingServer;
@JsonField(name = "externalSignalingTicket")
String externalSignalingTicket;
@JsonField(name = "externalSignalingServer")
String externalSignalingServer;
@JsonField(name = "externalSignalingTicket")
String externalSignalingTicket;
}

View File

@ -25,14 +25,14 @@ import lombok.Data;
@Data
public class ImportAccount {
public String username;
@Nullable
public String token;
public String baseUrl;
public String username;
@Nullable
public String token;
public String baseUrl;
public ImportAccount(String username, @Nullable String token, String baseUrl) {
this.username = username;
this.token = token;
this.baseUrl = baseUrl;
}
public ImportAccount(String username, @Nullable String token, String baseUrl) {
this.username = username;
this.token = token;
this.baseUrl = baseUrl;
}
}

View File

@ -26,7 +26,7 @@ import org.parceler.Parcel;
@Parcel
@Data
public class LoginData {
String serverUrl;
String username;
String token;
String serverUrl;
String username;
String token;
}

View File

@ -26,6 +26,6 @@ import org.parceler.Parcel;
@Parcel
@Data
public class RetrofitBucket {
public String url;
public Map<String, String> queryMap;
public String url;
public Map<String, String> queryMap;
}

View File

@ -32,9 +32,9 @@ import org.parceler.Parcel;
@JsonObject
@Data
public class RingtoneSettings {
@JsonField(name = "ringtoneUri", typeConverter = UriTypeConverter.class)
@Nullable
Uri ringtoneUri;
@JsonField(name = "ringtoneName")
String ringtoneName;
@JsonField(name = "ringtoneUri", typeConverter = UriTypeConverter.class)
@Nullable
Uri ringtoneUri;
@JsonField(name = "ringtoneName")
String ringtoneName;
}

View File

@ -20,7 +20,6 @@
package com.nextcloud.talk.models;
import com.nextcloud.talk.models.database.UserEntity;
import lombok.Data;
import org.parceler.Parcel;
@ -28,6 +27,6 @@ import org.parceler.Parcel;
@Data
@Parcel
public class SignatureVerification {
boolean signatureValid;
UserEntity userEntity;
boolean signatureValid;
UserEntity userEntity;
}

View File

@ -28,12 +28,12 @@ import java.io.Serializable;
@Entity
public interface ArbitraryStorage extends Parcelable, Persistable, Serializable {
@Key
long getAccountIdentifier();
@Key
long getAccountIdentifier();
String getKey();
String getKey();
String getObject();
String getObject();
String getValue();
String getValue();
}

View File

@ -33,98 +33,103 @@ import java.util.HashMap;
@Entity
public interface User extends Parcelable, Persistable, Serializable {
String TAG = "UserEntity";
String TAG = "UserEntity";
@Key
@Generated
long getId();
@Key
@Generated
long getId();
String getUserId();
String getUserId();
String getUsername();
String getUsername();
String getBaseUrl();
String getBaseUrl();
String getToken();
String getToken();
String getDisplayName();
String getDisplayName();
String getPushConfigurationState();
String getPushConfigurationState();
String getCapabilities();
String getCapabilities();
String getClientCertificate();
String getClientCertificate();
String getExternalSignalingServer();
String getExternalSignalingServer();
boolean getCurrent();
boolean getCurrent();
boolean getScheduledForDeletion();
boolean getScheduledForDeletion();
default boolean hasNotificationsCapability(String capabilityName) {
if (getCapabilities() != null) {
try {
Capabilities capabilities = LoganSquare.parse(getCapabilities(), Capabilities.class);
if (capabilities.getNotificationsCapability() != null && capabilities.getNotificationsCapability().getFeatures() != null) {
return capabilities.getSpreedCapability().getFeatures().contains(capabilityName);
}
} catch (IOException e) {
Log.e(TAG, "Failed to get capabilities for the user");
}
default boolean hasNotificationsCapability(String capabilityName) {
if (getCapabilities() != null) {
try {
Capabilities capabilities = LoganSquare.parse(getCapabilities(), Capabilities.class);
if (capabilities.getNotificationsCapability() != null
&& capabilities.getNotificationsCapability().getFeatures() != null) {
return capabilities.getSpreedCapability().getFeatures().contains(capabilityName);
}
return false;
} catch (IOException e) {
Log.e(TAG, "Failed to get capabilities for the user");
}
}
return false;
}
default boolean hasExternalCapability(String capabilityName) {
if (getCapabilities() != null) {
try {
Capabilities capabilities = LoganSquare.parse(getCapabilities(), Capabilities.class);
if (capabilities.getExternalCapability() != null && capabilities.getExternalCapability().containsKey("v1")) {
return capabilities.getExternalCapability().get("v1").contains("capabilityName");
}
} catch (IOException e) {
Log.e(TAG, "Failed to get capabilities for the user");
}
default boolean hasExternalCapability(String capabilityName) {
if (getCapabilities() != null) {
try {
Capabilities capabilities = LoganSquare.parse(getCapabilities(), Capabilities.class);
if (capabilities.getExternalCapability() != null && capabilities.getExternalCapability()
.containsKey("v1")) {
return capabilities.getExternalCapability().get("v1").contains("capabilityName");
}
return false;
} catch (IOException e) {
Log.e(TAG, "Failed to get capabilities for the user");
}
}
return false;
}
default boolean hasSpreedFeatureCapability(String capabilityName) {
if (getCapabilities() != null) {
try {
Capabilities capabilities = LoganSquare.parse(getCapabilities(), Capabilities.class);
if (capabilities != null && capabilities.getSpreedCapability() != null &&
capabilities.getSpreedCapability().getFeatures() != null) {
return capabilities.getSpreedCapability().getFeatures().contains(capabilityName);
}
} catch (IOException e) {
Log.e(TAG, "Failed to get capabilities for the user");
}
default boolean hasSpreedFeatureCapability(String capabilityName) {
if (getCapabilities() != null) {
try {
Capabilities capabilities = LoganSquare.parse(getCapabilities(), Capabilities.class);
if (capabilities != null && capabilities.getSpreedCapability() != null &&
capabilities.getSpreedCapability().getFeatures() != null) {
return capabilities.getSpreedCapability().getFeatures().contains(capabilityName);
}
return false;
} catch (IOException e) {
Log.e(TAG, "Failed to get capabilities for the user");
}
}
return false;
}
default int getMessageMaxLength() {
if (getCapabilities() != null) {
Capabilities capabilities = null;
try {
capabilities = LoganSquare.parse(getCapabilities(), Capabilities.class);
if (capabilities != null && capabilities.getSpreedCapability() != null && capabilities.getSpreedCapability().getConfig() != null
&& capabilities.getSpreedCapability().getConfig().containsKey("chat")) {
HashMap<String, String> chatConfigHashMap = capabilities.getSpreedCapability().getConfig().get("chat");
if (chatConfigHashMap != null && chatConfigHashMap.containsKey("max-length")) {
int chatSize = Integer.parseInt(chatConfigHashMap.get("max-length"));
if (chatSize > 0) {
return chatSize;
} else {
return 1000;
}
}
}
} catch (IOException e) {
e.printStackTrace();
default int getMessageMaxLength() {
if (getCapabilities() != null) {
Capabilities capabilities = null;
try {
capabilities = LoganSquare.parse(getCapabilities(), Capabilities.class);
if (capabilities != null
&& capabilities.getSpreedCapability() != null
&& capabilities.getSpreedCapability().getConfig() != null
&& capabilities.getSpreedCapability().getConfig().containsKey("chat")) {
HashMap<String, String> chatConfigHashMap =
capabilities.getSpreedCapability().getConfig().get("chat");
if (chatConfigHashMap != null && chatConfigHashMap.containsKey("max-length")) {
int chatSize = Integer.parseInt(chatConfigHashMap.get("max-length"));
if (chatSize > 0) {
return chatSize;
} else {
return 1000;
}
}
}
return 1000;
} catch (IOException e) {
e.printStackTrace();
}
}
return 1000;
}
}

View File

@ -31,6 +31,6 @@ import org.parceler.Parcel;
@Data
@JsonObject
public class AutocompleteOCS extends GenericOCS {
@JsonField(name = "data")
List<AutocompleteUser> data;
@JsonField(name = "data")
List<AutocompleteUser> data;
}

View File

@ -29,6 +29,6 @@ import org.parceler.Parcel;
@Data
@JsonObject
public class AutocompleteOverall {
@JsonField(name = "ocs")
AutocompleteOCS ocs;
@JsonField(name = "ocs")
AutocompleteOCS ocs;
}

View File

@ -29,12 +29,12 @@ import org.parceler.Parcel;
@Data
@JsonObject
public class AutocompleteUser {
@JsonField(name = "id")
String id;
@JsonField(name = "id")
String id;
@JsonField(name = "label")
String label;
@JsonField(name = "label")
String label;
@JsonField(name = "source")
String source;
@JsonField(name = "source")
String source;
}

View File

@ -31,15 +31,15 @@ import org.parceler.Parcel;
@Data
@JsonObject
public class Capabilities {
@JsonField(name = "spreed")
SpreedCapability spreedCapability;
@JsonField(name = "spreed")
SpreedCapability spreedCapability;
@JsonField(name = "notifications")
NotificationsCapability notificationsCapability;
@JsonField(name = "notifications")
NotificationsCapability notificationsCapability;
@JsonField(name = "theming")
ThemingCapability themingCapability;
@JsonField(name = "theming")
ThemingCapability themingCapability;
@JsonField(name = "external")
HashMap<String, List<String>> externalCapability;
@JsonField(name = "external")
HashMap<String, List<String>> externalCapability;
}

View File

@ -29,6 +29,6 @@ import org.parceler.Parcel;
@Data
@JsonObject
public class CapabilitiesList {
@JsonField(name = "capabilities")
Capabilities capabilities;
@JsonField(name = "capabilities")
Capabilities capabilities;
}

View File

@ -29,6 +29,6 @@ import org.parceler.Parcel;
@Parcel
@JsonObject
public class CapabilitiesOCS extends GenericOCS {
@JsonField(name = "data")
CapabilitiesList data;
@JsonField(name = "data")
CapabilitiesList data;
}

View File

@ -28,6 +28,6 @@ import org.parceler.Parcel;
@Parcel
@JsonObject
public class CapabilitiesOverall {
@JsonField(name = "ocs")
CapabilitiesOCS ocs;
@JsonField(name = "ocs")
CapabilitiesOCS ocs;
}

View File

@ -30,6 +30,6 @@ import org.parceler.Parcel;
@Data
@JsonObject
public class NotificationsCapability {
@JsonField(name = "ocs-endpoints")
List<String> features;
@JsonField(name = "ocs-endpoints")
List<String> features;
}

View File

@ -31,9 +31,9 @@ import org.parceler.Parcel;
@Data
@JsonObject
public class SpreedCapability {
@JsonField(name = "features")
List<String> features;
@JsonField(name = "features")
List<String> features;
@JsonField(name = "config")
HashMap<String, HashMap<String, String>> config;
@JsonField(name = "config")
HashMap<String, HashMap<String, String>> config;
}

View File

@ -29,33 +29,33 @@ import org.parceler.Parcel;
@Data
@JsonObject
class ThemingCapability {
@JsonField(name = "name")
String name;
@JsonField(name = "name")
String name;
@JsonField(name = "url")
String url;
@JsonField(name = "url")
String url;
@JsonField(name = "slogan")
String slogan;
@JsonField(name = "slogan")
String slogan;
@JsonField(name = "color")
String color;
@JsonField(name = "color")
String color;
@JsonField(name = "color-text")
String colorText;
@JsonField(name = "color-text")
String colorText;
@JsonField(name = "color-element")
String colorElement;
@JsonField(name = "color-element")
String colorElement;
@JsonField(name = "logo")
String logo;
@JsonField(name = "logo")
String logo;
@JsonField(name = "background")
String background;
@JsonField(name = "background")
String background;
@JsonField(name = "background-plain")
boolean backgroundPlain;
@JsonField(name = "background-plain")
boolean backgroundPlain;
@JsonField(name = "background-default")
boolean backgroundDefault;
@JsonField(name = "background-default")
boolean backgroundDefault;
}

View File

@ -45,233 +45,269 @@ import org.parceler.Parcel;
@Data
@JsonObject
public class ChatMessage implements IMessage, MessageContentType, MessageContentType.Image {
@JsonIgnore
public boolean isGrouped;
@JsonIgnore
public boolean isOneToOneConversation;
@JsonIgnore
public UserEntity activeUser;
@JsonIgnore
public Map<String, String> selectedIndividualHashMap;
@JsonIgnore
public boolean isLinkPreviewAllowed;
List<MessageType> messageTypesToIgnore = Arrays.asList(MessageType.REGULAR_TEXT_MESSAGE,
MessageType.SYSTEM_MESSAGE, MessageType.SINGLE_LINK_VIDEO_MESSAGE,
MessageType.SINGLE_LINK_AUDIO_MESSAGE, MessageType.SINGLE_LINK_MESSAGE);
@JsonField(name = "id")
public int jsonMessageId;
@JsonField(name = "token")
public String token;
// guests or users
@JsonField(name = "actorType")
public String actorType;
@JsonField(name = "actorId")
public String actorId;
// send when crafting a message
@JsonField(name = "actorDisplayName")
public String actorDisplayName;
@JsonField(name = "timestamp")
public long timestamp;
// send when crafting a message, max 1000 lines
@JsonField(name = "message")
public String message;
@JsonField(name = "messageParameters")
public HashMap<String, HashMap<String, String>> messageParameters;
@JsonField(name = "systemMessage", typeConverter = EnumSystemMessageTypeConverter.class)
public SystemMessageType systemMessageType;
@JsonIgnore
public boolean isGrouped;
@JsonIgnore
public boolean isOneToOneConversation;
@JsonIgnore
public UserEntity activeUser;
@JsonIgnore
public Map<String, String> selectedIndividualHashMap;
@JsonIgnore
public boolean isLinkPreviewAllowed;
@JsonField(name = "id")
public int jsonMessageId;
@JsonField(name = "token")
public String token;
// guests or users
@JsonField(name = "actorType")
public String actorType;
@JsonField(name = "actorId")
public String actorId;
// send when crafting a message
@JsonField(name = "actorDisplayName")
public String actorDisplayName;
@JsonField(name = "timestamp")
public long timestamp;
// send when crafting a message, max 1000 lines
@JsonField(name = "message")
public String message;
@JsonField(name = "messageParameters")
public HashMap<String, HashMap<String, String>> messageParameters;
@JsonField(name = "systemMessage", typeConverter = EnumSystemMessageTypeConverter.class)
public SystemMessageType systemMessageType;
List<MessageType> messageTypesToIgnore = Arrays.asList(MessageType.REGULAR_TEXT_MESSAGE,
MessageType.SYSTEM_MESSAGE, MessageType.SINGLE_LINK_VIDEO_MESSAGE,
MessageType.SINGLE_LINK_AUDIO_MESSAGE, MessageType.SINGLE_LINK_MESSAGE);
private boolean hasFileAttachment() {
if (messageParameters != null && messageParameters.size() > 0) {
for (String key : messageParameters.keySet()) {
Map<String, String> individualHashMap = messageParameters.get(key);
if (individualHashMap.get("type").equals("file")) {
return true;
}
}
private boolean hasFileAttachment() {
if (messageParameters != null && messageParameters.size() > 0) {
for (String key : messageParameters.keySet()) {
Map<String, String> individualHashMap = messageParameters.get(key);
if (individualHashMap.get("type").equals("file")) {
return true;
}
return false;
}
}
@Nullable
@Override
public String getImageUrl() {
if (messageParameters != null && messageParameters.size() > 0) {
for (String key : messageParameters.keySet()) {
Map<String, String> individualHashMap = messageParameters.get(key);
if (individualHashMap.get("type").equals("file")) {
selectedIndividualHashMap = individualHashMap;
return (ApiUtils.getUrlForFilePreviewWithFileId(getActiveUser().getBaseUrl(),
individualHashMap.get("id"), NextcloudTalkApplication.Companion.getSharedApplication().getResources().getDimensionPixelSize(R.dimen.maximum_file_preview_size)));
}
}
return false;
}
@Nullable
@Override
public String getImageUrl() {
if (messageParameters != null && messageParameters.size() > 0) {
for (String key : messageParameters.keySet()) {
Map<String, String> individualHashMap = messageParameters.get(key);
if (individualHashMap.get("type").equals("file")) {
selectedIndividualHashMap = individualHashMap;
return (ApiUtils.getUrlForFilePreviewWithFileId(getActiveUser().getBaseUrl(),
individualHashMap.get("id"), NextcloudTalkApplication.Companion.getSharedApplication()
.getResources()
.getDimensionPixelSize(R.dimen.maximum_file_preview_size)));
}
if (!messageTypesToIgnore.contains(getMessageType()) && isLinkPreviewAllowed) {
return getMessage().trim();
}
return null;
}
}
public MessageType getMessageType() {
if (!TextUtils.isEmpty(getSystemMessage())) {
return MessageType.SYSTEM_MESSAGE;
}
if (hasFileAttachment()) {
return MessageType.SINGLE_NC_ATTACHMENT_MESSAGE;
}
return TextMatchers.getMessageTypeFromString(getText());
if (!messageTypesToIgnore.contains(getMessageType()) && isLinkPreviewAllowed) {
return getMessage().trim();
}
public Map<String, String> getSelectedIndividualHashMap() {
return selectedIndividualHashMap;
return null;
}
public MessageType getMessageType() {
if (!TextUtils.isEmpty(getSystemMessage())) {
return MessageType.SYSTEM_MESSAGE;
}
public void setSelectedIndividualHashMap(Map<String, String> selectedIndividualHashMap) {
this.selectedIndividualHashMap = selectedIndividualHashMap;
if (hasFileAttachment()) {
return MessageType.SINGLE_NC_ATTACHMENT_MESSAGE;
}
@Override
public String getId() {
return Integer.toString(jsonMessageId);
}
return TextMatchers.getMessageTypeFromString(getText());
}
@Override
public String getText() {
return ChatUtils.getParsedMessage(getMessage(), getMessageParameters());
}
public Map<String, String> getSelectedIndividualHashMap() {
return selectedIndividualHashMap;
}
public String getLastMessageDisplayText() {
if (getMessageType().equals(MessageType.REGULAR_TEXT_MESSAGE) || getMessageType().equals(MessageType.SYSTEM_MESSAGE)) {
return getText();
public void setSelectedIndividualHashMap(Map<String, String> selectedIndividualHashMap) {
this.selectedIndividualHashMap = selectedIndividualHashMap;
}
@Override
public String getId() {
return Integer.toString(jsonMessageId);
}
@Override
public String getText() {
return ChatUtils.getParsedMessage(getMessage(), getMessageParameters());
}
public String getLastMessageDisplayText() {
if (getMessageType().equals(MessageType.REGULAR_TEXT_MESSAGE) || getMessageType().equals(
MessageType.SYSTEM_MESSAGE)) {
return getText();
} else {
if (getMessageType().equals(MessageType.SINGLE_LINK_GIPHY_MESSAGE)
|| getMessageType().equals(MessageType.SINGLE_LINK_TENOR_MESSAGE)
|| getMessageType().equals(MessageType.SINGLE_LINK_GIF_MESSAGE)) {
if (getActorId().equals(getActiveUser().getUserId())) {
return (NextcloudTalkApplication.Companion.getSharedApplication()
.getString(R.string.nc_sent_a_gif_you));
} else {
if (getMessageType().equals(MessageType.SINGLE_LINK_GIPHY_MESSAGE)
|| getMessageType().equals(MessageType.SINGLE_LINK_TENOR_MESSAGE)
|| getMessageType().equals(MessageType.SINGLE_LINK_GIF_MESSAGE)) {
if (getActorId().equals(getActiveUser().getUserId())) {
return (NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_sent_a_gif_you));
} else {
return (String.format(NextcloudTalkApplication.Companion.getSharedApplication().getResources().getString(R.string.nc_sent_a_gif),
!TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName() : NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest)));
}
} else if (getMessageType().equals(MessageType.SINGLE_NC_ATTACHMENT_MESSAGE)) {
if (getActorId().equals(getActiveUser().getUserId())) {
return (NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_sent_an_attachment_you));
} else {
return (String.format(NextcloudTalkApplication.Companion.getSharedApplication().getResources().getString(R.string.nc_sent_an_attachment),
!TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName() : NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest)));
}
} else if (getMessageType().equals(MessageType.SINGLE_LINK_MESSAGE)) {
if (getActorId().equals(getActiveUser().getUserId())) {
return (NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_sent_a_link_you));
} else {
return (String.format(NextcloudTalkApplication.Companion.getSharedApplication().getResources().getString(R.string.nc_sent_a_link),
!TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName() : NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest)));
}
} else if (getMessageType().equals(MessageType.SINGLE_LINK_AUDIO_MESSAGE)) {
if (getActorId().equals(getActiveUser().getUserId())) {
return (NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_sent_an_audio_you));
} else {
return (String.format(NextcloudTalkApplication.Companion.getSharedApplication().getResources().getString(R.string.nc_sent_an_audio),
!TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName() : NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest)));
}
} else if (getMessageType().equals(MessageType.SINGLE_LINK_VIDEO_MESSAGE)) {
if (getActorId().equals(getActiveUser().getUserId())) {
return (NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_sent_a_video_you));
} else {
return (String.format(NextcloudTalkApplication.Companion.getSharedApplication().getResources().getString(R.string.nc_sent_a_video),
!TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName() : NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest)));
}
} else if (getMessageType().equals(MessageType.SINGLE_LINK_IMAGE_MESSAGE)) {
if (getActorId().equals(getActiveUser().getUserId())) {
return (NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_sent_an_image_you));
} else {
return (String.format(NextcloudTalkApplication.Companion.getSharedApplication().getResources().getString(R.string.nc_sent_an_image),
!TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName() : NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest)));
}
}
return (String.format(NextcloudTalkApplication.Companion.getSharedApplication()
.getResources()
.getString(R.string.nc_sent_a_gif),
!TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName()
: NextcloudTalkApplication.Companion.getSharedApplication()
.getString(R.string.nc_guest)));
}
return "";
} else if (getMessageType().equals(MessageType.SINGLE_NC_ATTACHMENT_MESSAGE)) {
if (getActorId().equals(getActiveUser().getUserId())) {
return (NextcloudTalkApplication.Companion.getSharedApplication()
.getString(R.string.nc_sent_an_attachment_you));
} else {
return (String.format(NextcloudTalkApplication.Companion.getSharedApplication()
.getResources()
.getString(R.string.nc_sent_an_attachment),
!TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName()
: NextcloudTalkApplication.Companion.getSharedApplication()
.getString(R.string.nc_guest)));
}
} else if (getMessageType().equals(MessageType.SINGLE_LINK_MESSAGE)) {
if (getActorId().equals(getActiveUser().getUserId())) {
return (NextcloudTalkApplication.Companion.getSharedApplication()
.getString(R.string.nc_sent_a_link_you));
} else {
return (String.format(NextcloudTalkApplication.Companion.getSharedApplication()
.getResources()
.getString(R.string.nc_sent_a_link),
!TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName()
: NextcloudTalkApplication.Companion.getSharedApplication()
.getString(R.string.nc_guest)));
}
} else if (getMessageType().equals(MessageType.SINGLE_LINK_AUDIO_MESSAGE)) {
if (getActorId().equals(getActiveUser().getUserId())) {
return (NextcloudTalkApplication.Companion.getSharedApplication()
.getString(R.string.nc_sent_an_audio_you));
} else {
return (String.format(NextcloudTalkApplication.Companion.getSharedApplication()
.getResources()
.getString(R.string.nc_sent_an_audio),
!TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName()
: NextcloudTalkApplication.Companion.getSharedApplication()
.getString(R.string.nc_guest)));
}
} else if (getMessageType().equals(MessageType.SINGLE_LINK_VIDEO_MESSAGE)) {
if (getActorId().equals(getActiveUser().getUserId())) {
return (NextcloudTalkApplication.Companion.getSharedApplication()
.getString(R.string.nc_sent_a_video_you));
} else {
return (String.format(NextcloudTalkApplication.Companion.getSharedApplication()
.getResources()
.getString(R.string.nc_sent_a_video),
!TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName()
: NextcloudTalkApplication.Companion.getSharedApplication()
.getString(R.string.nc_guest)));
}
} else if (getMessageType().equals(MessageType.SINGLE_LINK_IMAGE_MESSAGE)) {
if (getActorId().equals(getActiveUser().getUserId())) {
return (NextcloudTalkApplication.Companion.getSharedApplication()
.getString(R.string.nc_sent_an_image_you));
} else {
return (String.format(NextcloudTalkApplication.Companion.getSharedApplication()
.getResources()
.getString(R.string.nc_sent_an_image),
!TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName()
: NextcloudTalkApplication.Companion.getSharedApplication()
.getString(R.string.nc_guest)));
}
}
}
@Override
public IUser getUser() {
return new IUser() {
@Override
public String getId() {
return actorId;
}
return "";
}
@Override
public String getName() {
return actorDisplayName;
}
@Override
public IUser getUser() {
return new IUser() {
@Override
public String getId() {
return actorId;
}
@Override
public String getAvatar() {
if (getActorType().equals("users")) {
return ApiUtils.getUrlForAvatarWithName(getActiveUser().getBaseUrl(), actorId, R.dimen.avatar_size);
} else if (getActorType().equals("guests")) {
String apiId =
NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest);
@Override
public String getName() {
return actorDisplayName;
}
if (!TextUtils.isEmpty(getActorDisplayName())) {
apiId = getActorDisplayName();
}
return ApiUtils.getUrlForAvatarWithNameForGuests(getActiveUser().getBaseUrl(), apiId, R.dimen.avatar_size);
} else {
return null;
}
}
};
}
@Override
public String getAvatar() {
if (getActorType().equals("users")) {
return ApiUtils.getUrlForAvatarWithName(getActiveUser().getBaseUrl(), actorId,
R.dimen.avatar_size);
} else if (getActorType().equals("guests")) {
String apiId =
NextcloudTalkApplication.Companion.getSharedApplication()
.getString(R.string.nc_guest);
@Override
public Date getCreatedAt() {
return new Date(timestamp * 1000L);
}
if (!TextUtils.isEmpty(getActorDisplayName())) {
apiId = getActorDisplayName();
}
return ApiUtils.getUrlForAvatarWithNameForGuests(getActiveUser().getBaseUrl(), apiId,
R.dimen.avatar_size);
} else {
return null;
}
}
};
}
@Override
public String getSystemMessage() {
return new EnumSystemMessageTypeConverter().convertToString(getSystemMessageType());
}
@Override
public Date getCreatedAt() {
return new Date(timestamp * 1000L);
}
public enum MessageType {
REGULAR_TEXT_MESSAGE,
SYSTEM_MESSAGE,
SINGLE_LINK_GIPHY_MESSAGE,
SINGLE_LINK_TENOR_MESSAGE,
SINGLE_LINK_GIF_MESSAGE,
SINGLE_LINK_MESSAGE,
SINGLE_LINK_VIDEO_MESSAGE,
SINGLE_LINK_IMAGE_MESSAGE,
SINGLE_LINK_AUDIO_MESSAGE,
SINGLE_NC_ATTACHMENT_MESSAGE,
}
@Override
public String getSystemMessage() {
return new EnumSystemMessageTypeConverter().convertToString(getSystemMessageType());
}
public enum SystemMessageType {
DUMMY,
CONVERSATION_CREATED,
CONVERSATION_RENAMED,
CALL_STARTED,
CALL_JOINED,
CALL_LEFT,
CALL_ENDED,
GUESTS_ALLOWED,
GUESTS_DISALLOWED,
PASSWORD_SET,
PASSWORD_REMOVED,
USER_ADDED,
USER_REMOVED,
MODERATOR_PROMOTED,
MODERATOR_DEMOTED,
FILE_SHARED,
LOBBY_NONE,
LOBBY_NON_MODERATORS,
LOBBY_OPEN_TO_EVERYONE
}
public enum MessageType {
REGULAR_TEXT_MESSAGE,
SYSTEM_MESSAGE,
SINGLE_LINK_GIPHY_MESSAGE,
SINGLE_LINK_TENOR_MESSAGE,
SINGLE_LINK_GIF_MESSAGE,
SINGLE_LINK_MESSAGE,
SINGLE_LINK_VIDEO_MESSAGE,
SINGLE_LINK_IMAGE_MESSAGE,
SINGLE_LINK_AUDIO_MESSAGE,
SINGLE_NC_ATTACHMENT_MESSAGE,
}
public enum SystemMessageType {
DUMMY,
CONVERSATION_CREATED,
CONVERSATION_RENAMED,
CALL_STARTED,
CALL_JOINED,
CALL_LEFT,
CALL_ENDED,
GUESTS_ALLOWED,
GUESTS_DISALLOWED,
PASSWORD_SET,
PASSWORD_REMOVED,
USER_ADDED,
USER_REMOVED,
MODERATOR_PROMOTED,
MODERATOR_DEMOTED,
FILE_SHARED,
LOBBY_NONE,
LOBBY_NON_MODERATORS,
LOBBY_OPEN_TO_EVERYONE
}
}

View File

@ -30,6 +30,6 @@ import org.parceler.Parcel;
@Parcel
@JsonObject
public class ChatOCS extends GenericOCS {
@JsonField(name = "data")
public List<ChatMessage> data;
@JsonField(name = "data")
public List<ChatMessage> data;
}

Some files were not shown because too many files have changed in this diff Show More