diff --git a/Habitica/AndroidManifest.xml b/Habitica/AndroidManifest.xml
index 7f91b8e52..8467ed430 100644
--- a/Habitica/AndroidManifest.xml
+++ b/Habitica/AndroidManifest.xml
@@ -122,7 +122,7 @@
diff --git a/Habitica/res/drawable/edittext.xml b/Habitica/res/drawable/edittext.xml
new file mode 100644
index 000000000..d396af7fa
--- /dev/null
+++ b/Habitica/res/drawable/edittext.xml
@@ -0,0 +1,16 @@
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Habitica/res/layout/activity_group_form.xml b/Habitica/res/layout/activity_group_form.xml
index 517c53e16..ff463a65f 100644
--- a/Habitica/res/layout/activity_group_form.xml
+++ b/Habitica/res/layout/activity_group_form.xml
@@ -2,62 +2,130 @@
+ android:layout_height="match_parent"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:background="@color/gray_700">
+ android:layout_height="wrap_content"
+ android:paddingTop="30dp"
+ android:background="@color/white">
+
+
+
+
+
-
+
+ android:inputType="textCapSentences"
+ android:background="@color/transparent"
+ android:paddingStart="@dimen/spacing_large"
+ android:paddingEnd="@dimen/spacing_large"
+ android:paddingBottom="@dimen/spacing_large"
+ android:paddingTop="20dp"
+ android:textColorHint="@color/gray_50"
+ />
-
-
-
-
+ app:hintTextAppearance="@style/TextAppearance.AppCompat"
+ android:layout_marginTop="@dimen/spacing_large"
+ android:layout_marginLeft="@dimen/spacing_large"
+ android:layout_marginRight="@dimen/spacing_large"
+ android:background="@drawable/edittext"
+ android:textColorHint="@color/gray_50">
-
+ android:inputType="textCapSentences|textMultiLine"
+ android:background="@color/transparent"
+ android:paddingStart="@dimen/spacing_large"
+ android:paddingEnd="@dimen/spacing_large"
+ android:paddingBottom="@dimen/spacing_large"
+ android:paddingTop="20dp"
+ android:textColorHint="@color/gray_50"
+ android:minLines="3"
+ android:gravity="top" />
-
+
+
+
+
+
+
+ android:id="@+id/privacyWrapper"
+ android:layout_marginLeft="@dimen/spacing_large"
+ android:layout_marginRight="@dimen/spacing_large"
+ tools:visibility="gone">
+
\ No newline at end of file
diff --git a/Habitica/res/layout/fragment_group_info.xml b/Habitica/res/layout/fragment_group_info.xml
index 5ae396d9d..abc7e0d84 100644
--- a/Habitica/res/layout/fragment_group_info.xml
+++ b/Habitica/res/layout/fragment_group_info.xml
@@ -111,7 +111,7 @@
style="@style/HabiticaButton.Gray.600"
android:background="@drawable/layout_rounded_bg_gray_700"
android:textSize="16sp"
- android:text="@string/create_party_website"
+ android:text="@string/create_party"
android:layout_marginTop="@dimen/spacing_large"/>
+
\ No newline at end of file
diff --git a/Habitica/res/navigation/navigation.xml b/Habitica/res/navigation/navigation.xml
index 2f01491ca..40212fd73 100644
--- a/Habitica/res/navigation/navigation.xml
+++ b/Habitica/res/navigation/navigation.xml
@@ -256,4 +256,8 @@
android:name="userID"
app:argType="string" />
+
\ No newline at end of file
diff --git a/Habitica/res/values/strings.xml b/Habitica/res/values/strings.xml
index 5e49214d9..140a931c5 100644
--- a/Habitica/res/values/strings.xml
+++ b/Habitica/res/values/strings.xml
@@ -860,5 +860,8 @@
Discover
Damage paused
Important Announcements
+ Create
+ Only leader can create Challenges
+ Create Party
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/api/ApiService.java b/Habitica/src/main/java/com/habitrpg/android/habitica/api/ApiService.java
index 55e2eec9c..6da989670 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/api/ApiService.java
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/api/ApiService.java
@@ -201,6 +201,9 @@ public interface ApiService {
@GET("groups/{gid}")
Flowable> getGroup(@Path("gid") String groupId);
+ @POST("groups")
+ Flowable> createGroup(@Body Group item);
+
@PUT("groups/{id}")
Flowable> updateGroup(@Path("id") String id, @Body Group item);
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/ApiClient.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/ApiClient.kt
index 40bc07022..587de93b6 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/ApiClient.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/ApiClient.kt
@@ -129,6 +129,7 @@ interface ApiClient {
fun getGroup(groupId: String): Flowable
+ fun createGroup(group: Group): Flowable
fun updateGroup(id: String, item: Group): Flowable
fun listGroupChat(groupId: String): Flowable>
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/SocialRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/SocialRepository.kt
index 3f8eb5d2f..ea6f4055e 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/SocialRepository.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/SocialRepository.kt
@@ -36,7 +36,8 @@ interface SocialRepository : BaseRepository {
fun joinGroup(id: String?): Flowable
- fun updateGroup(group: Group?, name: String?, description: String?, leader: String?, privacy: String?): Flowable
+ fun createGroup(name: String?, description: String?, leader: String?, type: String?, privacy: String?, leaderCreateChallenge: Boolean?): Flowable
+ fun updateGroup(group: Group?, name: String?, description: String?, leader: String?, leaderCreateChallenge: Boolean?): Flowable
fun retrieveGroups(type: String): Flowable>
fun getGroups(type: String): Flowable>
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt
index 66dfe714d..2d3810e15 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt
@@ -63,6 +63,7 @@ class ApiClientImpl//private OnHabitsAPIResult mResultListener;
//private HostConfig mConfig;
(private val gsonConverter: GsonConverterFactory, override val hostConfig: HostConfig, private val crashlyticsProxy: CrashlyticsProxy, private val popupNotificationsManager: PopupNotificationsManager, private val context: Context) : Consumer, ApiClient {
+
private lateinit var retrofitAdapter: Retrofit
// I think we don't need the ApiClientImpl anymore we could just use ApiService
@@ -476,6 +477,10 @@ class ApiClientImpl//private OnHabitsAPIResult mResultListener;
return apiService.getGroup(groupId).compose(configureApiCallObserver())
}
+ override fun createGroup(group: Group): Flowable {
+ return apiService.createGroup(group).compose(configureApiCallObserver())
+ }
+
override fun updateGroup(id: String, item: Group): Flowable {
return apiService.updateGroup(id, item).compose(configureApiCallObserver())
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/SocialRepositoryImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/SocialRepositoryImpl.kt
index 38182c1f3..bc8dfb224 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/SocialRepositoryImpl.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/SocialRepositoryImpl.kt
@@ -19,6 +19,7 @@ import io.realm.RealmResults
class SocialRepositoryImpl(localRepository: SocialLocalRepository, apiClient: ApiClient, userID: String) : BaseRepositoryImpl(localRepository, apiClient, userID), SocialRepository {
+
override fun getGroupMembership(id: String): Flowable {
return localRepository.getGroupMembership(userID, id)
}
@@ -131,7 +132,19 @@ class SocialRepositoryImpl(localRepository: SocialLocalRepository, apiClient: Ap
}
}
- override fun updateGroup(group: Group?, name: String?, description: String?, leader: String?, privacy: String?): Flowable {
+ override fun createGroup(name: String?, description: String?, leader: String?, type: String?, privacy: String?, leaderCreateChallenge: Boolean?): Flowable {
+ val group = Group()
+ group.name = name
+ group.description = description
+ group.type = type
+ group.leaderID = leader
+ group.privacy = privacy
+ return apiClient.createGroup(group).doOnNext {
+ localRepository.save(it)
+ }
+ }
+
+ override fun updateGroup(group: Group?, name: String?, description: String?, leader: String?, leaderCreateChallenge: Boolean?): Flowable {
if (group == null) {
return Flowable.empty()
}
@@ -139,7 +152,7 @@ class SocialRepositoryImpl(localRepository: SocialLocalRepository, apiClient: Ap
copiedGroup.name = name
copiedGroup.description = description
copiedGroup.leaderID = leader
- copiedGroup.privacy = privacy
+ copiedGroup.leaderOnlyChallenges = leaderCreateChallenge ?: false
localRepository.save(copiedGroup)
return apiClient.updateGroup(copiedGroup.id, copiedGroup)
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/social/Group.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/models/social/Group.kt
index c40af66dc..8fc53f7f0 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/social/Group.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/social/Group.kt
@@ -13,34 +13,22 @@ open class Group : RealmObject() {
@SerializedName("_id")
@PrimaryKey
var id: String = ""
-
var balance: Double = 0.toDouble()
-
var description: String? = null
-
var summary: String? = null
-
var leaderID: String? = null
-
var leaderName: String? = null
-
var name: String? = null
-
var memberCount: Int = 0
-
var type: String? = null
-
var logo: String? = null
-
var quest: Quest? = null
-
var privacy: String? = null
-
var members: RealmList? = null
-
var challengeCount: Int = 0
-
var leaderMessage: String? = null
+ var leaderOnlyChallenges: Boolean = false
+ var leaderOnlyGetGems: Boolean = false
override fun equals(other: Any?): Boolean {
if (this === other) {
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/GroupFormActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/GroupFormActivity.kt
index 7ef2a6941..d31365e34 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/GroupFormActivity.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/GroupFormActivity.kt
@@ -1,45 +1,35 @@
package com.habitrpg.android.habitica.ui.activities
import android.app.Activity
-import android.content.Context
import android.content.Intent
import android.os.Bundle
-import androidx.core.content.ContextCompat
-import android.view.KeyEvent
-import android.view.Menu
-import android.view.MenuItem
import android.view.View
-import android.view.inputmethod.InputMethodManager
-import android.widget.EditText
-import android.widget.ImageButton
-import android.widget.LinearLayout
-import android.widget.Spinner
+import android.widget.*
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.components.AppComponent
-import com.habitrpg.android.habitica.ui.helpers.KeyboardUtil
-import com.habitrpg.android.habitica.ui.helpers.MarkdownParser
-import com.habitrpg.android.habitica.ui.helpers.bindView
-import net.pherth.android.emoji_library.EmojiEditText
-import net.pherth.android.emoji_library.EmojiPopup
+import com.habitrpg.android.habitica.extensions.notNull
+import com.habitrpg.android.habitica.ui.helpers.*
class GroupFormActivity : BaseActivity() {
private var groupID: String? = null
+ private var groupType: String? = null
private var groupName: String? = null
private var groupDescription: String? = null
private var groupPrivacy: String? = null
private var groupLeader: String? = null
+ private var leaderCreateChallenge = false
- private val groupNameEditText: EditText by bindView(R.id.group_name_edittext)
- private val groupDescriptionEditText: EmojiEditText by bindView(R.id.group_description_edittext)
- internal val emojiButton: ImageButton by bindView(R.id.emoji_toggle_btn)
- internal val privacyWrapper: LinearLayout by bindView(R.id.privacyWrapper)
+ private val cancelButton: ImageButton by bindView(R.id.cancel_button)
+ private val saveButton: Button by bindView(R.id.save_button)
+ private val groupNameEditText: MultiAutoCompleteTextView by bindView(R.id.group_name_edittext)
+ private val groupDescriptionEditText: MultiAutoCompleteTextView by bindView(R.id.group_description_edittext)
+ private val leaderCreateChallengeSwitch: Switch by bindView(R.id.leader_create_challenge_switch)
+ private val privacyWrapper: LinearLayout by bindView(R.id.privacyWrapper)
internal val privacySpinner: Spinner by bindView(R.id.privacySpinner)
+ private val privacySeparator: View by bindView(R.id.privacy_separator)
- private val popup: EmojiPopup by lazy {
- EmojiPopup(emojiButton.rootView, this, ContextCompat.getColor(this, R.color.brand))
- }
-
+ private var autocompleteAdapter: AutocompleteAdapter? = null
override fun getLayoutResId(): Int {
return R.layout.activity_group_form
@@ -48,61 +38,34 @@ class GroupFormActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- val intent = intent
- val bundle = intent.extras
- this.groupID = bundle!!.getString("groupID")
- this.groupName = bundle.getString("name")
- this.groupDescription = bundle.getString("description")
- this.groupPrivacy = bundle.getString("privacy")
- this.groupLeader = bundle.getString("leader")
-
- // Emoji keyboard stuff
-
- popup
-
- popup.setSizeForSoftKeyboard()
- popup.setOnDismissListener { changeEmojiKeyboardIcon(false) }
- popup.setOnSoftKeyboardOpenCloseListener(object : EmojiPopup.OnSoftKeyboardOpenCloseListener {
-
- override fun onKeyboardOpen(keyBoardHeight: Int) {
- }
-
- override fun onKeyboardClose() {
- if (popup.isShowing) {
- popup.dismiss()
- }
- }
- })
-
- popup.setOnEmojiconClickedListener { emojicon ->
- if (currentFocus == null || !isEmojiEditText(currentFocus) || emojicon == null) {
- return@setOnEmojiconClickedListener
- }
- val emojiEditText = currentFocus as? EmojiEditText
- val start = emojiEditText?.selectionStart ?: 0
- val end = emojiEditText?.selectionEnd ?: 0
- if (start < 0) {
- emojiEditText?.append(emojicon.emoji)
- } else {
- emojiEditText?.text?.replace(Math.min(start, end),
- Math.max(start, end), emojicon.emoji, 0,
- emojicon.emoji.length)
- }
+ intent.extras.notNull {bundle ->
+ groupID = bundle.getString("groupID")
+ groupType = bundle.getString("groupType")
+ groupName = bundle.getString("name")
+ groupDescription = bundle.getString("description")
+ groupPrivacy = bundle.getString("privacy")
+ groupLeader = bundle.getString("leader")
+ leaderCreateChallenge = bundle.getBoolean("leaderCreateChallenge", false)
}
- popup.setOnEmojiconBackspaceClickedListener { _ ->
- if (isEmojiEditText(currentFocus)) {
- val event = KeyEvent(
- 0, 0, 0, KeyEvent.KEYCODE_DEL, 0, 0, 0, 0, KeyEvent.KEYCODE_ENDCALL)
- currentFocus?.dispatchKeyEvent(event)
- }
+ if (groupType == "party") {
+ privacyWrapper.visibility = View.GONE
+ privacySeparator.visibility = View.GONE
}
- emojiButton.setOnClickListener(EmojiClickListener(groupDescriptionEditText))
-
- if (this.groupID != null) {
- this.fillForm()
+ if (groupID != null) {
+ fillForm()
}
+
+ cancelButton.setOnClickListener {
+ finish()
+ KeyboardUtil.dismissKeyboard(this)
+ }
+
+ saveButton.setOnClickListener {
+ finishActivitySuccessfuly()
+ }
+
}
@@ -111,43 +74,11 @@ class GroupFormActivity : BaseActivity() {
}
private fun fillForm() {
- this.groupNameEditText.setText(this.groupName)
- this.groupDescriptionEditText.setText(this.groupDescription)
- this.privacyWrapper.visibility = View.GONE
- }
-
- override fun onCreateOptionsMenu(menu: Menu): Boolean {
- // Inflate the menu; this adds items to the action bar if it is present.
- menuInflater.inflate(R.menu.menu_save, menu)
- return true
- }
-
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- // Handle action bar item clicks here. The action bar will
- // automatically handle clicks on the Home/Up button, so long
- // as you specify a parent activity in AndroidManifest.xml.
- val id = item.itemId
-
-
- if (id == R.id.action_save_changes) {
- finishActivitySuccessfuly()
- return true
- }
-
- return super.onOptionsItemSelected(item)
- }
-
- private fun isEmojiEditText(view: View?): Boolean {
- return view is EmojiEditText
- }
-
- private fun changeEmojiKeyboardIcon(keyboardOpened: Boolean) {
-
- if (keyboardOpened) {
- emojiButton.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_keyboard_grey600_24dp))
- } else {
- emojiButton.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_emoticon_grey600_24dp))
- }
+ groupNameEditText.setText(groupName)
+ groupDescriptionEditText.setText(groupDescription)
+ leaderCreateChallengeSwitch.isChecked = leaderCreateChallenge
+ privacyWrapper.visibility = View.GONE
+ saveButton.text = getString(R.string.save)
}
override fun onSupportNavigateUp(): Boolean {
@@ -165,7 +96,9 @@ class GroupFormActivity : BaseActivity() {
val resultIntent = Intent()
val bundle = Bundle()
bundle.putString("name", this.groupNameEditText.text.toString())
+ bundle.putString("groupType", groupType)
bundle.putString("description", MarkdownParser.parseCompiled(this.groupDescriptionEditText.text))
+ bundle.putBoolean("leaderCreateChallenge", leaderCreateChallengeSwitch.isActivated)
bundle.putString("leader", this.groupLeader)
resultIntent.putExtras(bundle)
setResult(Activity.RESULT_OK, resultIntent)
@@ -173,28 +106,6 @@ class GroupFormActivity : BaseActivity() {
KeyboardUtil.dismissKeyboard(this)
}
- private inner class EmojiClickListener(internal var view: EmojiEditText) : View.OnClickListener {
-
- override fun onClick(v: View) {
- if (!popup.isShowing) {
- if (popup.isKeyBoardOpen == true) {
- popup.showAtBottom()
- changeEmojiKeyboardIcon(true)
- } else {
- view.isFocusableInTouchMode = true
- view.requestFocus()
- popup.showAtBottomPending()
- val inputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
- inputMethodManager.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT)
- changeEmojiKeyboardIcon(true)
- }
- } else {
- popup.dismiss()
- changeEmojiKeyboardIcon(false)
- }
- }
- }
-
companion object {
const val GROUP_FORM_ACTIVITY = 11
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/GroupInformationFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/GroupInformationFragment.kt
index 34444df0d..c2301b58b 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/GroupInformationFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/GroupInformationFragment.kt
@@ -1,5 +1,6 @@
package com.habitrpg.android.habitica.ui.fragments.social
+import android.app.Activity
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
@@ -7,24 +8,24 @@ import android.content.Intent
import android.graphics.Bitmap
import android.graphics.Shader
import android.graphics.drawable.BitmapDrawable
-import android.net.Uri
import android.os.Bundle
import android.text.method.LinkMovementMethod
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import androidx.core.net.toUri
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.components.AppComponent
import com.habitrpg.android.habitica.data.SocialRepository
import com.habitrpg.android.habitica.data.UserRepository
import com.habitrpg.android.habitica.extensions.backgroundCompat
import com.habitrpg.android.habitica.extensions.notNull
+import com.habitrpg.android.habitica.helpers.MainNavigationController
import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.models.invitations.PartyInvite
import com.habitrpg.android.habitica.models.members.Member
import com.habitrpg.android.habitica.models.social.Group
import com.habitrpg.android.habitica.models.user.User
+import com.habitrpg.android.habitica.ui.activities.GroupFormActivity
import com.habitrpg.android.habitica.ui.activities.MainActivity
import com.habitrpg.android.habitica.ui.fragments.BaseFragment
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils
@@ -71,7 +72,7 @@ class GroupInformationFragment : BaseFragment() {
updateGroup(group)
- buttonPartyInviteAccept.setOnClickListener { _ ->
+ buttonPartyInviteAccept.setOnClickListener {
val userId = user?.invitations?.party?.id
if (userId != null) {
socialRepository.joinGroup(userId)
@@ -83,7 +84,7 @@ class GroupInformationFragment : BaseFragment() {
}
}
- buttonPartyInviteReject.setOnClickListener { _ ->
+ buttonPartyInviteReject.setOnClickListener {
val userId = user?.invitations?.party?.id
if (userId != null) {
socialRepository.rejectGroupInvite(userId)
@@ -91,7 +92,7 @@ class GroupInformationFragment : BaseFragment() {
}
}
- username_textview.setOnClickListener { _ ->
+ username_textview.setOnClickListener {
val clipboard = context?.getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager
val clip = ClipData.newPlainText(context?.getString(R.string.username), user?.username)
clipboard?.primaryClip = clip
@@ -102,16 +103,21 @@ class GroupInformationFragment : BaseFragment() {
}
craetePartyButton.setOnClickListener {
- val browserIntent = Intent(Intent.ACTION_VIEW, "https://habitica.com/party".toUri())
- startActivity(browserIntent)
+ val bundle = Bundle()
+ bundle.putString("groupType", "party")
+ bundle.putString("leader", user?.id)
+ val intent = Intent(activity, GroupFormActivity::class.java)
+ intent.putExtras(bundle)
+ intent.flags = Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
+ startActivityForResult(intent, GroupFormActivity.GROUP_FORM_ACTIVITY)
}
context.notNull { context ->
- DataBindingUtils.loadImage("timeTravelersShop_background_fall") {
- val aspectRatio = it.width / it.height.toFloat()
+ DataBindingUtils.loadImage("timeTravelersShop_background_fall") {bitmap ->
+ val aspectRatio = bitmap.width / bitmap.height.toFloat()
val height = context.resources.getDimension(R.dimen.shop_height).toInt()
val width = Math.round(height * aspectRatio)
- val drawable = BitmapDrawable(context.resources, Bitmap.createScaledBitmap(it, width, height, false))
+ val drawable = BitmapDrawable(context.resources, Bitmap.createScaledBitmap(bitmap, width, height, false))
drawable.tileModeX = Shader.TileMode.REPEAT
Observable.just(drawable)
.observeOn(AndroidSchedulers.mainThread())
@@ -125,6 +131,37 @@ class GroupInformationFragment : BaseFragment() {
groupSummaryView.movementMethod = LinkMovementMethod.getInstance()
}
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ super.onActivityResult(requestCode, resultCode, data)
+ when (requestCode) {
+ GroupFormActivity.GROUP_FORM_ACTIVITY -> {
+ if (resultCode == Activity.RESULT_OK) {
+ val bundle = data?.extras
+ if (bundle?.getString("groupType") == "party") {
+ socialRepository.createGroup(bundle.getString("name"),
+ bundle.getString("description"),
+ bundle.getString("leader"),
+ "party",
+ bundle.getString("privacy"),
+ bundle.getBoolean("leaderCreateChallenge"))
+ .flatMap {
+ userRepository.retrieveUser(false)
+ }
+ .subscribe(Consumer {
+ }, RxErrorHandler.handleEmptyError())
+ } else {
+ this.socialRepository.updateGroup(this.group,
+ bundle?.getString("name"),
+ bundle?.getString("description"),
+ bundle?.getString("leader"),
+ bundle?.getBoolean("leaderCreateChallenge"))
+ .subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
+ }
+ }
+ }
+ }
+ }
+
private fun refresh() {
if (group != null) {
compositeSubscription.add(socialRepository.retrieveGroup(group?.id ?: "").subscribe(Consumer {}, RxErrorHandler.handleEmptyError()))
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/GuildFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/GuildFragment.kt
index eae523ffe..bd0737096 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/GuildFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/GuildFragment.kt
@@ -180,11 +180,13 @@ class GuildFragment : BaseMainFragment() {
private fun displayEditForm() {
val bundle = Bundle()
- bundle.putString("groupID", this.guild?.id)
- bundle.putString("name", this.guild?.name)
- bundle.putString("description", this.guild?.description)
- bundle.putString("privacy", this.guild?.privacy)
- bundle.putString("leader", this.guild?.leaderID)
+ bundle.putString("groupID", guild?.id)
+ bundle.putString("name", guild?.name)
+ bundle.putString("description", guild?.description)
+ bundle.putString("privacy", guild?.privacy)
+ bundle.putString("leader", guild?.leaderID)
+ bundle.putBoolean("leaderCreateChallenge", guild?.leaderOnlyChallenges ?: true)
+
val intent = Intent(activity, GroupFormActivity::class.java)
intent.putExtras(bundle)
@@ -202,7 +204,7 @@ class GuildFragment : BaseMainFragment() {
bundle?.getString("name"),
bundle?.getString("description"),
bundle?.getString("leader"),
- bundle?.getString("privacy"))
+ bundle?.getBoolean("leaderCreateChallenge"))
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
}
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyDetailFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyDetailFragment.kt
index 26548ea5a..a4a0dbbf2 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyDetailFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyDetailFragment.kt
@@ -195,7 +195,7 @@ class PartyDetailFragment constructor(private val viewModel: PartyViewModel) : B
val builder = AlertDialog.Builder(activity)
.setMessage(R.string.leave_party_confirmation)
.setPositiveButton(R.string.yes) { _, _ ->
- viewModel.leaveGroup { activity?.supportFragmentManager?.beginTransaction()?.remove(this)?.commit() }
+ viewModel.leaveGroup { }
}.setNegativeButton(R.string.no) { _, _ -> }
builder.show()
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyFragment.kt
index be24967fe..48acd9528 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyFragment.kt
@@ -12,8 +12,7 @@ import androidx.lifecycle.ViewModelProviders
import androidx.viewpager.widget.ViewPager
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.components.AppComponent
-import com.habitrpg.android.habitica.extensions.notNull
-import com.habitrpg.android.habitica.helpers.RemoteConfigManager
+import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.models.social.Group
import com.habitrpg.android.habitica.ui.activities.GroupFormActivity
import com.habitrpg.android.habitica.ui.activities.PartyInviteActivity
@@ -24,15 +23,14 @@ import com.habitrpg.android.habitica.ui.helpers.bindView
import com.habitrpg.android.habitica.ui.helpers.resetViews
import com.habitrpg.android.habitica.ui.viewmodels.GroupViewType
import com.habitrpg.android.habitica.ui.viewmodels.PartyViewModel
+import io.reactivex.functions.Consumer
import java.util.*
-import javax.inject.Inject
+
class PartyFragment : BaseMainFragment() {
- @Inject
- lateinit var configRepository: RemoteConfigManager
-
private val viewPager: ViewPager? by bindView(R.id.viewPager)
+ private var firstFragment: Fragment? = null
private var partyMemberListFragment: PartyMemberListFragment? = null
private var chatFragment: ChatFragment? = null
private var viewPagerAdapter: androidx.fragment.app.FragmentPagerAdapter? = null
@@ -62,10 +60,26 @@ class PartyFragment : BaseMainFragment() {
viewModel.loadPartyID()
- // Get the full group data
- if (userHasParty()) {
- viewModel.retrieveGroup {}
- }
+ compositeSubscription.add(userRepository.getUser()
+ .map {
+ it.hasParty()
+ }
+ .distinctUntilChanged()
+ .subscribe(Consumer {
+ val fragment = firstFragment
+ if (fragment != null) {
+ childFragmentManager.beginTransaction().remove(fragment).commit()
+ }
+ viewPager?.adapter?.notifyDataSetChanged()
+
+ if (it) {
+ viewModel.retrieveGroup {}
+ tabLayout?.visibility = View.VISIBLE
+ } else {
+ tabLayout?.visibility = View.GONE
+ }
+
+ }, RxErrorHandler.handleEmptyError()))
viewPager?.currentItem = 0
@@ -74,10 +88,6 @@ class PartyFragment : BaseMainFragment() {
this.tutorialText = getString(R.string.tutorial_party)
}
- private fun userHasParty(): Boolean {
- return user?.party?.id?.isNotEmpty() == true
- }
-
override fun injectFragment(component: AppComponent) {
component.inject(this)
}
@@ -102,6 +112,9 @@ class PartyFragment : BaseMainFragment() {
if (group != null && this.user != null) {
if (group.leaderID == this.user?.id) {
inflater.inflate(R.menu.menu_party_admin, menu)
+ if (group.memberCount > 1) {
+ menu.findItem(R.id.menu_guild_leave).isVisible = false
+ }
} else {
inflater.inflate(R.menu.menu_party, menu)
}
@@ -128,9 +141,6 @@ class PartyFragment : BaseMainFragment() {
.setMessage(context?.getString(R.string.leave_party_confirmation))
.setPositiveButton(context?.getString(R.string.yes)) { _, _ ->
viewModel.leaveGroup {
- parentFragment.notNull { fragment ->
- activity?.supportFragmentManager?.beginTransaction()?.remove(fragment)?.commit()
- }
}
}
.setNegativeButton(context?.getString(R.string.no)) { dialog, _ -> dialog.dismiss() }
@@ -147,8 +157,10 @@ class PartyFragment : BaseMainFragment() {
val group = viewModel.getGroupData().value
bundle.putString("groupID", group?.id)
bundle.putString("name", group?.name)
+ bundle.putString("groupType", group?.type)
bundle.putString("description", group?.description)
bundle.putString("leader", group?.leaderID)
+ bundle.putBoolean("leaderCreateChallenge", group?.leaderOnlyChallenges ?: false)
val intent = Intent(activity, GroupFormActivity::class.java)
intent.putExtras(bundle)
@@ -161,7 +173,7 @@ class PartyFragment : BaseMainFragment() {
when (requestCode) {
GroupFormActivity.GROUP_FORM_ACTIVITY -> {
if (resultCode == Activity.RESULT_OK) {
- viewModel.updateGroup(data?.extras)
+ viewModel.updateOrCreateGroup(data?.extras)
}
}
PartyInviteActivity.RESULT_SEND_INVITES -> {
@@ -201,18 +213,19 @@ class PartyFragment : BaseMainFragment() {
override fun getItem(position: Int): androidx.fragment.app.Fragment {
return when (position) {
0 -> {
- if (user?.hasParty() == true) {
+ firstFragment = if (user?.hasParty() == true) {
val detailFragment = PartyDetailFragment(viewModel)
detailFragment
} else {
GroupInformationFragment.newInstance(null, user)
}
+ firstFragment
}
1 -> {
if (chatFragment == null) {
chatFragment = ChatFragment(viewModel)
}
- chatFragment ?: Fragment()
+ chatFragment
}
2 -> {
if (partyMemberListFragment == null) {
@@ -221,15 +234,15 @@ class PartyFragment : BaseMainFragment() {
partyMemberListFragment?.setPartyId(user?.party?.id ?: "")
}
}
- partyMemberListFragment ?: Fragment()
+ partyMemberListFragment
}
else -> Fragment()
- }
+ } ?: Fragment()
}
override fun getCount(): Int {
- return if (viewModel.getGroupData().value == null) {
+ return if (user?.hasParty() != true) {
1
} else {
3
@@ -244,6 +257,14 @@ class PartyFragment : BaseMainFragment() {
else -> ""
} ?: ""
}
+
+ override fun getItemPosition(fragment: Any): Int {
+ return if ((fragment is GroupInformationFragment && user?.hasParty() == true) || (fragment is PartyDetailFragment && user?.hasParty() != true)) {
+ POSITION_NONE
+ } else {
+ POSITION_UNCHANGED
+ }
+ }
}
this.viewPager?.adapter = viewPagerAdapter
@@ -266,6 +287,4 @@ class PartyFragment : BaseMainFragment() {
})
tabLayout?.setupWithViewPager(viewPager)
}
-
-
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/AutocompleteAdapter.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/AutocompleteAdapter.kt
index 3e60ff49e..b189158cd 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/AutocompleteAdapter.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/AutocompleteAdapter.kt
@@ -27,7 +27,7 @@ class AutocompleteAdapter(val context: Context, val socialRepository: SocialRepo
override fun performFiltering(constraint: CharSequence?): FilterResults {
val filterResults = FilterResults()
if (constraint != null && constraint.isNotEmpty()) {
- if (constraint[0] == '@' && socialRepository != null) {
+ if (constraint[0] == '@' && constraint.length >= 3 && socialRepository != null) {
isAutocompletingUsers = true
userResults = socialRepository.findUsernames(constraint.toString().drop(1), autocompleteContext, groupID).blockingFirst(arrayListOf())
filterResults.values = userResults
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/GroupViewModel.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/GroupViewModel.kt
index d05dc1489..45dfb45cf 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/GroupViewModel.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/GroupViewModel.kt
@@ -89,15 +89,23 @@ open class GroupViewModel: BaseViewModel() {
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError()))
}
- fun updateGroup(bundle: Bundle?) {
+
+
+ fun updateOrCreateGroup(bundle: Bundle?) {
if (group.value == null) {
- return
+ socialRepository.createGroup(bundle?.getString("name"),
+ bundle?.getString("description"),
+ bundle?.getString("leader"),
+ bundle?.getString("groupType"),
+ bundle?.getString("privacy"),
+ bundle?.getBoolean("leaderCreateChallenge"))
+ } else {
+ disposable.add(socialRepository.updateGroup(group.value, bundle?.getString("name"),
+ bundle?.getString("description"),
+ bundle?.getString("leader"),
+ bundle?.getBoolean("leaderCreateChallenge"))
+ .subscribe(Consumer { }, RxErrorHandler.handleEmptyError()))
}
- disposable.add(socialRepository.updateGroup(group.value, bundle?.getString("name"),
- bundle?.getString("description"),
- bundle?.getString("leader"),
- bundle?.getString("privacy"))
- .subscribe(Consumer { }, RxErrorHandler.handleEmptyError()))
}
fun leaveGroup(function: () -> Unit) {
@@ -148,10 +156,13 @@ open class GroupViewModel: BaseViewModel() {
}
fun retrieveGroupChat(onComplete: () -> Unit) {
- groupIDSubject.value?.value.notNull {
- disposable.add(socialRepository.retrieveGroupChat(it).subscribe(Consumer {
- onComplete()
- }, RxErrorHandler.handleEmptyError()))
+ val groupID = groupIDSubject.value?.value
+ if (groupID.isNullOrEmpty()) {
+ onComplete()
+ return
}
+ disposable.add(socialRepository.retrieveGroupChat(groupID).subscribe(Consumer {
+ onComplete()
+ }, RxErrorHandler.handleEmptyError()))
}
}
\ No newline at end of file
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/utils/GroupSerialization.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/utils/GroupSerialization.kt
index d980b861f..74c4aa26d 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/utils/GroupSerialization.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/utils/GroupSerialization.kt
@@ -106,6 +106,16 @@ class GroupSerialization : JsonDeserializer, JsonSerializer {
}
}
}
+
+ if (obj.has("leaderOnly")) {
+ val leaderOnly = obj.getAsJsonObject("leaderOnly")
+ if (leaderOnly.has("challenges")) {
+ group.leaderOnlyChallenges = leaderOnly.get("challenges").asBoolean
+ }
+ if (leaderOnly.has("getGems")) {
+ group.leaderOnlyGetGems = leaderOnly.get("getGems").asBoolean
+ }
+ }
return group
}
@@ -118,6 +128,10 @@ class GroupSerialization : JsonDeserializer, JsonSerializer {
obj.addProperty("type", src.type)
obj.addProperty("type", src.type)
obj.addProperty("leader", src.leaderID)
+ val leaderOnly = JsonObject()
+ leaderOnly.addProperty("challenges", src.leaderOnlyChallenges)
+ leaderOnly.addProperty("getGems", src.leaderOnlyGetGems)
+ obj.add("leaderOnly", leaderOnly)
return obj
}
}