Skip to content

Instantly share code, notes, and snippets.

@luck-alex13
Created September 17, 2020 11:21
Show Gist options
  • Save luck-alex13/4a6a362dcf42707a050affa71fd08a13 to your computer and use it in GitHub Desktop.
Save luck-alex13/4a6a362dcf42707a050affa71fd08a13 to your computer and use it in GitHub Desktop.
Примеры кода
class AuthActivityVM(application: Application) : BaseAndroidViewModel(application), LifecycleObserver {
var authClient = DokiMainClient.create(UserConfig.getServerUrl())
fun changePass(oldPass: String, newPass: String) {
vmState.postValue(ViewModelState.ProgressState(true))
compositeDisposable.add(
makeAsync(authClient.changePassword(oldPass, newPass))
.subscribe({
vmState.postValue(ViewModelState.SuccessChangePass())
}, {
vmState.postValue(
ViewModelState.ErrorState(
handleRequestError(it)
)
)
})
)
}
fun getUserLinks() {
compositeDisposable.add(
makeAsync(authClient.getUserLinks())
.subscribe({
vmState.postValue(ViewModelState.SuccessState(it))
}, {
vmState.postValue(
ViewModelState.ErrorState(
handleRequestError(it)
)
)
})
)
}
fun bindVk(token: String) {
vmState.postValue(ViewModelState.ProgressState(true))
compositeDisposable.add(
makeAsync(
authClient.bindVk(token)
).subscribe({
toast(getContext(), getContext().getString(R.string.social_account_bind_success))
getUserLinks()
}, {
vmState.postValue(
ViewModelState.ErrorState(
handleRequestError(it)
)
)
})
)
}
fun unbindVk() {
vmState.postValue(ViewModelState.ProgressState(true))
compositeDisposable.add(
makeAsync(authClient.unbindVk())
.subscribe({
toast(getContext(), getContext().getString(R.string.social_account_unbind_success))
getUserLinks()
}, {
vmState.postValue(
ViewModelState.ErrorState(
handleRequestError(it)
)
)
})
)
}
fun bindFb(token: String) {
vmState.postValue(ViewModelState.ProgressState(true))
compositeDisposable.add(
makeAsync(
authClient.bindFb(token)
).subscribe({
toast(getContext(), getContext().getString(R.string.social_account_bind_success))
getUserLinks()
}, {
vmState.postValue(
ViewModelState.ErrorState(
handleRequestError(it)
)
)
})
)
}
fun unbindFb() {
vmState.postValue(ViewModelState.ProgressState(true))
compositeDisposable.add(
makeAsync(authClient.unbindFb())
.subscribe({
toast(getContext(), getContext().getString(R.string.social_account_unbind_success))
getUserLinks()
}, {
vmState.postValue(
ViewModelState.ErrorState(
handleRequestError(it)
)
)
})
)
}
}
class AuthorizeActivity : AuthActivity() {
private val RC_SIGN_IN = 100
private var progress: AlertDialog? = null
private lateinit var viewModel: AuthActivityVM
private lateinit var callbackManager: CallbackManager
private lateinit var callbackVK: VKAuthCallback
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_authorize)
hideSocialContainers()
viewModel = ViewModelProvider(this).get(AuthActivityVM::class.java)
lifecycle.addObserver(viewModel)
viewModel.vmState.observe(this, Observer<ViewModelState> {
when (it) {
is ViewModelState.SuccessChangePass -> {
progress?.cancel()
toast(this, getString(R.string.password_changed))
}
is ViewModelState.SuccessState<*> -> {
progress?.cancel()
if (it.result is SocialLinks) {
setupSocialLinks(it.result)
}
}
is ViewModelState.ProgressState -> {
progress = AlertManager.buildProgress(this).create()
progress!!.show()
}
is ViewModelState.ErrorState -> {
progressBar.visibility = View.GONE
progress?.cancel()
toast(this, it.errorText)
}
}
})
viewModel.getUserLinks()
editPassButton.setOnClickListener {
editPasswordButtonClicked(it)
}
changeNumberBtn.setOnClickListener {
EditPhoneDialog(this)
.setSaveCallback(Callback<String> {
logd(it)
}).show()
}
}
override fun onResume() {
DokiApplication.wasBackgrounded = false
super.onResume()
}
fun backButtonClicked(view: View) {
this.onBackPressed()
}
fun editPasswordButtonClicked(view: View) {
val dialog = EditPassDialog(this).apply {
setSaveCallback(Callback<List<String>> {
viewModel.changePass(it[0], it[1])
})
}
dialog.show()
}
fun setupSocialLinks(links: SocialLinks) {
progressBar.visibility = View.GONE
//setupGoogle(links.googleId)
setupVk(links.vkontakteId)
setupFb(links.facebookId)
}
fun setupGoogle(userId: String?) {
googleContainer.visibility = View.VISIBLE
setupSocialUI(userId, googleAccTV, bindGoogleBtn)
}
fun setupVk(userId: String?) {
vkContainer.visibility = View.VISIBLE
setupSocialUI(userId, vkAccTV, bindVkBtn)
bindVkBtn.setOnClickListener {
if (userId == null) {
VK.login(this, arrayListOf(VKScope.EMAIL))
} else {
UnbindAccountDialog(this)
.setSaveCallback(SimpleCallback {
viewModel.unbindVk()
})
.show()
}
}
callbackVK = object : VKAuthCallback {
override fun onLogin(token: VKAccessToken) {
viewModel.bindVk(token.accessToken)
}
override fun onLoginFailed(errorCode: Int) {
if (errorCode != VKAuthCallback.AUTH_CANCELED) {
toastLong(this@AuthorizeActivity, getString(R.string.unhandled_error_vk_auth))
}
}
}
}
fun setupFb(userId: String?) {
fbContainer.visibility = View.VISIBLE
setupSocialUI(userId, fbAccTV, bindFbBtn)
callbackManager = CallbackManager.Factory.create();
val callback = object : FacebookCallback<LoginResult> {
override fun onSuccess(loginResult: LoginResult) {
viewModel.bindFb(loginResult.accessToken.token)
}
override fun onCancel() {
loge("Facebook onCancel")
}
override fun onError(exception: FacebookException) {
loge(exception)
toast(this@AuthorizeActivity, exception.localizedMessage)
}
}
LoginManager.getInstance().registerCallback(callbackManager, callback)
// Callback registration
//sign_in_facebook_button.registerCallback(callbackManager, callback)
bindFbBtn.setOnClickListener {
if (userId == null) {
LoginManager.getInstance().logInWithReadPermissions(this, listOf("public_profile", "email"));
} else {
UnbindAccountDialog(this)
.setSaveCallback(SimpleCallback {
viewModel.unbindFb()
})
.show()
}
}
}
fun hideSocialContainers() {
googleContainer.visibility = View.GONE
vkContainer.visibility = View.GONE
fbContainer.visibility = View.GONE
}
fun setupSocialUI(userId: String?, textView: TextView, button: MaterialButton) {
if (userId == null) {
textView.setText(R.string.no_binding)
textView.setTextColor(ContextCompat.getColorStateList(this, R.color.grey_receipt))
button.setText(R.string.bind_action)
button.strokeWidth = dp2px(2f)
button.strokeWidth = 0
button.backgroundTintList = ContextCompat.getColorStateList(this, R.color.buttonColor)
} else {
textView.setText("ID: $userId")
textView.setTextColor(ContextCompat.getColorStateList(this, R.color.black_clear))
button.setText(R.string.unbind_action)
button.strokeWidth = dp2px(2f)
button.strokeColor = ContextCompat.getColorStateList(this, R.color.buttonColor)
button.backgroundTintList = ContextCompat.getColorStateList(this, R.color.white)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == RC_SIGN_IN) {
val task = GoogleSignIn.getSignedInAccountFromIntent(data)
//handleSignInResult(task)
} else {
if (data == null || !VK.onActivityResult(requestCode, resultCode, data, callbackVK)) {
callbackManager.onActivityResult(requestCode, resultCode, data);
super.onActivityResult(requestCode, resultCode, data)
}
}
}
}
open class BaseAndroidViewModel(application: Application) : AndroidViewModel(application), LifecycleObserver {
var progressState = MutableLiveData<Boolean>()
var vmState = SingleLiveEvent<ViewModelState>()
protected var dp: Disposable? = null
protected val compositeDisposable = CompositeDisposable()
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
open fun clearDisposables() {
compositeDisposable.clear()
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
open fun disposeDisposables() {
compositeDisposable.dispose()
dp?.dispose()
}
fun <T> makeAsync(func: Observable<T>): Observable<T> {
return func.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
}
fun makeAsync(func: Completable): Completable {
return func.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
}
}
sealed class ViewModelState {
class SuccessState<T>(val result: T): ViewModelState()
class SuccessState1() : ViewModelState()
class SuccessChangePass() : ViewModelState()
class SuccessChangePhone() : ViewModelState()
class SuccessAuth() : ViewModelState()
class SuccessBindSocial() : ViewModelState()
class SuccessUnbindSocial() : ViewModelState()
class SuccessRegistrationRequest() : ViewModelState()
class SuccessAuthDemo<T>(val result: T) : ViewModelState()
class SuccessAuthByGoogle<T>(val result: T) : ViewModelState()
class ErrorState(val errorText: CharSequence) : ViewModelState()
class SmallImageError : ViewModelState()
class BanState(val errorText: CharSequence) : ViewModelState()
class ProgressState(val inProgress: Boolean): ViewModelState()
class SubscriptionConfirmed<T>(val result: T): ViewModelState()
}
class EditPhoneDialog(context: Context) : Dialog(context, R.style.CustomDialogTheme) {
init {
ownerActivity = context as Activity
}
private var saveCallback: Callback<String>? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.dialog_edit_phone)
closeButton.setOnClickListener {
newPhoneEditText.hideKeyboard()
dismiss()
}
changeBtn.setOnClickListener {
validateFields()
}
setupPhoneEditText()
newPhoneEditText.showKeyboard()
}
private fun setupPhoneEditText() {
val mask = MaskImpl.createTerminated(PredefinedSlots.RUS_PHONE_NUMBER)
val watcher = MaskFormatWatcher(mask)
watcher.installOn(newPhoneEditText)
newPhoneEditText.onFocusChangeListener = View.OnFocusChangeListener { view, hasFocus ->
if (hasFocus && newPhoneEditText.text!!.isBlank()) {
// хак чтобы показать маску до ввода символа
newPhoneEditText.setText("l")
}
}
}
private fun validateFields() {
val newPhone = newPhoneEditText.text?.toString()
if (newPhone.isNullOrBlank()) {
newPhoneEditText.setError(context.getString(R.string.field_cant_be_empty))
return
}
dismiss()
saveCallback?.call(newPhone)
}
fun setSaveCallback(callback: Callback<String>): EditPhoneDialog {
saveCallback = callback
return this
}
}
// RecyclerView c разными типами и использованием Databinding
public class FriendsRVAdapter extends RecyclerView.Adapter<BaseViewHolder> {
private List<FriendListItem> listItems;
private OnItemClickListener<Friend> onItemClickListener;
private BindingListener bindingListener;
public FriendsRVAdapter() {
listItems = new ArrayList<>();
}
public void setListItems(List<FriendListItem> listItems) {
this.listItems = listItems;
notifyDataSetChanged();
}
@Override
public int getItemViewType(int position) {
return listItems.get(position).getType();
}
@Override
public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
int layoutRes = 0;
switch (viewType) {
case FriendListItem.ITEM_HEADER: {
layoutRes = R.layout.first_friend_item;
break;
}
case FriendListItem.ITEM_CONFIRMED_FRIEND: {
layoutRes = R.layout.friend_list_item;
break;
}
case FriendListItem.ITEM_PROGRESS: {
layoutRes = R.layout.progress_list_item;
break;
}
case FriendListItem.ITEM_INCOMING_FRIEND: {
layoutRes = R.layout.new_friend_item;
break;
}
}
View view = LayoutInflater.from(parent.getContext())
.inflate(layoutRes, parent, false);
return new BaseViewHolder(DataBindingUtil.bind(view));
}
@Override
public void onBindViewHolder(BaseViewHolder holder, int position) {
Friend friend = listItems.get(position).getFriend();
if (friend != null && friend.isValid()) {
holder.bindView(BR.friend, friend);
if (onItemClickListener != null) {
holder.getBinding().getRoot().setOnClickListener(v -> {
if (onItemClickListener != null)
onItemClickListener.onItemClick(v, position, listItems.get(position).getFriend());
});
}
int itemType = listItems.get(position).getType();
if (bindingListener != null && (itemType == FriendListItem.ITEM_HEADER || itemType == FriendListItem.ITEM_INCOMING_FRIEND)) {
bindingListener.onBindItem(holder.getBinding(), position, listItems.get(position).getFriend());
}
}
}
@Override
public int getItemCount() {
return listItems == null ? 0 : listItems.size();
}
public void setOnItemClickListener(OnItemClickListener<Friend> onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
public void setBindingListener(BindingListener bindingListener) {
this.bindingListener = bindingListener;
}
public interface BindingListener {
void onBindItem(ViewDataBinding binding, int position, Friend item);
}
}
class MainClient {
companion object Factory {
fun create(serverUrl: String): DokiMainApi {
val retrofit = Retrofit.Builder()
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.addConverterFactory(ScalarsConverterFactory.create())
.baseUrl(serverUrl + Const.Links.API)
.client(AuthOkHttpClient.create())
.build()
return retrofit.create(DokiMainApi::class.java);
}
}
}
class AuthOkHttpClient {
companion object {
val defaultTimeOut: Long = 1
fun create(): OkHttpClient {
return OkHttpClient.Builder()
.readTimeout(defaultTimeOut, TimeUnit.MINUTES)
.connectTimeout(defaultTimeOut, TimeUnit.MINUTES)
.writeTimeout(defaultTimeOut, TimeUnit.MINUTES)
.apply {
this.addNetworkInterceptor(authInterceptor())
if (BuildConfig.DEBUG) {
val logging = HttpLoggingInterceptor()
logging.level = HttpLoggingInterceptor.Level.BODY
this.addNetworkInterceptor(logging)
}
}
.build()
}
fun authInterceptor(): Interceptor {
return TokenInterceptor()
}
}
class TokenInterceptor() : Interceptor {
private val HEADER_AUTH = "Authorization"
private val BEARER = "Bearer"
@Throws(IOException::class)
override fun intercept(chain: Interceptor.Chain): Response {
val originalRequest = chain.request()
val builder: Request.Builder
builder = originalRequest.newBuilder()
.header(HEADER_AUTH, "$BEARER ${UserConfig.getAuthToken()}")
return chain.proceed(builder.build())
}
}
}
class SlideFragment : Fragment() {
var layoutRes: Int = R.layout.fragment_slide
var imageId: Int = -1
var textId: Int = -1
companion object {
@JvmStatic
fun newInstance(imageId: Int, textId: Int): SlideFragment =
SlideFragment().apply {
arguments = Bundle().apply {
putInt(Const.Extras.KEY_IMAGE, imageId)
putInt(Const.Extras.KEY_TEXT, textId)
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
imageId = it.getInt(Const.Extras.KEY_IMAGE)
textId = it.getInt(Const.Extras.KEY_TEXT)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(layoutRes, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
if (imageId > 0) {
slideImage.setImageResource(imageId)
}
if (textId > 0) {
slideText.setText(textId)
}
}
}
// туториал с табами
class TutorialActivity : AppCompatActivity(), ViewPager.OnPageChangeListener {
private lateinit var slidesFragmentAdapter: SlidesFragmentAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
this.setContentView(R.layout.tutotial_activity)
val pagesList = mutableListOf<Fragment>(
SlideFragment.newInstance(R.drawable.photo_slide, R.string.tutorial_first_slide),
SlideFragment.newInstance(R.drawable.search_slide, R.string.tutorial_second_slide),
SlideFragment.newInstance(R.drawable.packet_slide, R.string.tutorial_third_slide),
SlideFragment.newInstance(R.drawable.tools_slide, R.string.tutorial_fourth_slide)
)
slidesFragmentAdapter = SlidesFragmentAdapter(pagesList, supportFragmentManager)
slidesViewPager.adapter = slidesFragmentAdapter
slidesViewPager.addOnPageChangeListener(this)
indicator.attachToPager(slidesViewPager);
skipBtn.setOnClickListener {
openNextActivity()
}
nextBtn.setOnClickListener {
if (slidesViewPager.currentItem < slidesFragmentAdapter.count - 1) {
slidesViewPager.setCurrentItem(slidesViewPager.currentItem + 1, true)
} else {
openNextActivity()
}
}
}
fun openNextActivity() {
UserConfig.setTutorialShown(true)
val intent = Intent(this, LoginActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
}
startActivity(intent)
}
override fun onPageScrollStateChanged(state: Int) {
}
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
}
override fun onPageSelected(position: Int) {
when (position) {
0 -> {
}
1 -> {
}
2 -> {
nextBtn.setText(R.string.next)
}
3 -> {
nextBtn.setText(R.string.begin_action)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment