mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-11-03 16:23:54 +01:00
Added wikitalk page and improved bottomsheet for landscape mode
This commit is contained in:
parent
4545059035
commit
5f8592eb0a
18 changed files with 713 additions and 225 deletions
|
|
@ -14,6 +14,7 @@ import fr.free.nrw.commons.description.DescriptionEditActivity;
|
||||||
import fr.free.nrw.commons.explore.depictions.WikidataItemDetailsActivity;
|
import fr.free.nrw.commons.explore.depictions.WikidataItemDetailsActivity;
|
||||||
import fr.free.nrw.commons.explore.SearchActivity;
|
import fr.free.nrw.commons.explore.SearchActivity;
|
||||||
import fr.free.nrw.commons.media.ZoomableActivity;
|
import fr.free.nrw.commons.media.ZoomableActivity;
|
||||||
|
import fr.free.nrw.commons.nearby.WikidataFeedback;
|
||||||
import fr.free.nrw.commons.notification.NotificationActivity;
|
import fr.free.nrw.commons.notification.NotificationActivity;
|
||||||
import fr.free.nrw.commons.profile.ProfileActivity;
|
import fr.free.nrw.commons.profile.ProfileActivity;
|
||||||
import fr.free.nrw.commons.review.ReviewActivity;
|
import fr.free.nrw.commons.review.ReviewActivity;
|
||||||
|
|
@ -79,4 +80,7 @@ public abstract class ActivityBuilderModule {
|
||||||
|
|
||||||
@ContributesAndroidInjector
|
@ContributesAndroidInjector
|
||||||
abstract ZoomableActivity bindZoomableActivity();
|
abstract ZoomableActivity bindZoomableActivity();
|
||||||
|
|
||||||
|
@ContributesAndroidInjector
|
||||||
|
abstract WikidataFeedback bindWikiFeedback();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,11 @@ package fr.free.nrw.commons.di;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
|
import fr.free.nrw.commons.actions.PageEditClient;
|
||||||
import fr.free.nrw.commons.explore.categories.CategoriesModule;
|
import fr.free.nrw.commons.explore.categories.CategoriesModule;
|
||||||
import fr.free.nrw.commons.navtab.MoreBottomSheetFragment;
|
import fr.free.nrw.commons.navtab.MoreBottomSheetFragment;
|
||||||
import fr.free.nrw.commons.navtab.MoreBottomSheetLoggedOutFragment;
|
import fr.free.nrw.commons.navtab.MoreBottomSheetLoggedOutFragment;
|
||||||
|
import fr.free.nrw.commons.nearby.NearbyController;
|
||||||
import fr.free.nrw.commons.upload.worker.UploadWorker;
|
import fr.free.nrw.commons.upload.worker.UploadWorker;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
|
@ -68,6 +70,9 @@ public interface CommonsApplicationComponent extends AndroidInjector<Application
|
||||||
|
|
||||||
void inject(PicOfDayAppWidget picOfDayAppWidget);
|
void inject(PicOfDayAppWidget picOfDayAppWidget);
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
void inject(NearbyController nearbyController);
|
||||||
|
|
||||||
Gson gson();
|
Gson gson();
|
||||||
|
|
||||||
@Component.Builder
|
@Component.Builder
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,10 @@ import fr.free.nrw.commons.campaigns.CampaignResponseDTO;
|
||||||
import fr.free.nrw.commons.explore.depictions.DepictsClient;
|
import fr.free.nrw.commons.explore.depictions.DepictsClient;
|
||||||
import fr.free.nrw.commons.location.LatLng;
|
import fr.free.nrw.commons.location.LatLng;
|
||||||
import fr.free.nrw.commons.nearby.Place;
|
import fr.free.nrw.commons.nearby.Place;
|
||||||
import fr.free.nrw.commons.nearby.model.PlaceBindings;
|
|
||||||
import fr.free.nrw.commons.nearby.model.ItemsClass;
|
import fr.free.nrw.commons.nearby.model.ItemsClass;
|
||||||
import fr.free.nrw.commons.nearby.model.NearbyResponse;
|
import fr.free.nrw.commons.nearby.model.NearbyResponse;
|
||||||
import fr.free.nrw.commons.nearby.model.NearbyResultItem;
|
import fr.free.nrw.commons.nearby.model.NearbyResultItem;
|
||||||
|
import fr.free.nrw.commons.nearby.model.PlaceBindings;
|
||||||
import fr.free.nrw.commons.profile.achievements.FeaturedImages;
|
import fr.free.nrw.commons.profile.achievements.FeaturedImages;
|
||||||
import fr.free.nrw.commons.profile.achievements.FeedbackResponse;
|
import fr.free.nrw.commons.profile.achievements.FeedbackResponse;
|
||||||
import fr.free.nrw.commons.profile.leaderboard.LeaderboardResponse;
|
import fr.free.nrw.commons.profile.leaderboard.LeaderboardResponse;
|
||||||
|
|
@ -397,6 +397,31 @@ public class OkHttpJsonApiClient {
|
||||||
throw new Exception(response.message());
|
throw new Exception(response.message());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getWikidataTalk(String wikidataTitle)
|
||||||
|
throws Exception {
|
||||||
|
Timber.tag("PRINT").e(wikidataTitle);
|
||||||
|
final HttpUrl.Builder urlBuilder = HttpUrl
|
||||||
|
.parse("https://www.wikidata.org/w/api.php").newBuilder()
|
||||||
|
.addQueryParameter("action", "query")
|
||||||
|
.addQueryParameter("prop", "revisions")
|
||||||
|
.addQueryParameter("rvprop", "content")
|
||||||
|
.addQueryParameter("rvslots", "main")
|
||||||
|
.addQueryParameter("titles", wikidataTitle)
|
||||||
|
.addQueryParameter("format", "json");
|
||||||
|
|
||||||
|
final Request request = new Request.Builder()
|
||||||
|
.url(urlBuilder.build())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
final Response response = okHttpClient.newCall(request).execute();
|
||||||
|
if (response.body() != null && response.isSuccessful()) {
|
||||||
|
final String json = response.body().string();
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
throw new Exception(response.message());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make API Call to get Places
|
* Make API Call to get Places
|
||||||
*
|
*
|
||||||
|
|
@ -476,7 +501,7 @@ public class OkHttpJsonApiClient {
|
||||||
" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\">"
|
" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\">"
|
||||||
+ "\n<bounds minlat=\"$MIN_LATITUDE\" minlon=\"$MIN_LONGITUDE\" maxlat=\"$MAX_LATITUDE\" maxlon=\"$MAX_LONGITUDE\"/>";
|
+ "\n<bounds minlat=\"$MIN_LATITUDE\" minlon=\"$MIN_LONGITUDE\" maxlat=\"$MAX_LATITUDE\" maxlon=\"$MAX_LONGITUDE\"/>";
|
||||||
|
|
||||||
List<PlaceBindings> placeBindings = runQuery(leftLatLng,rightLatLng);
|
List<PlaceBindings> placeBindings = runQuery(leftLatLng, rightLatLng);
|
||||||
if (placeBindings != null) {
|
if (placeBindings != null) {
|
||||||
for (PlaceBindings item : placeBindings) {
|
for (PlaceBindings item : placeBindings) {
|
||||||
if (item.getItem() != null && item.getLabel() != null && item.getClas() != null) {
|
if (item.getItem() != null && item.getLabel() != null && item.getClas() != null) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
package fr.free.nrw.commons.nearby
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.View.OnLongClickListener
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.annotation.NonNull
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import fr.free.nrw.commons.R
|
||||||
|
import fr.free.nrw.commons.nearby.model.BottomSheetItem
|
||||||
|
|
||||||
|
|
||||||
|
class BottomSheetAdapter(context: Context?, private val itemList: List<BottomSheetItem>) :
|
||||||
|
RecyclerView.Adapter<BottomSheetAdapter.ViewHolder>() {
|
||||||
|
private val layoutInflater: LayoutInflater = LayoutInflater.from(context)
|
||||||
|
private var itemClickListener: ItemClickListener? = null
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
override fun onCreateViewHolder(@NonNull parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
|
val view: View = layoutInflater.inflate(R.layout.bottom_sheet_item_layout, parent, false)
|
||||||
|
return ViewHolder(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(@NonNull holder: ViewHolder, position: Int) {
|
||||||
|
val item = itemList[position]
|
||||||
|
holder.imageView.setImageDrawable(
|
||||||
|
ContextCompat.getDrawable(
|
||||||
|
getContext(),
|
||||||
|
item.imageResourceId
|
||||||
|
)
|
||||||
|
)
|
||||||
|
holder.title.setText(item.title)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int {
|
||||||
|
return itemList.size
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateBookmarkIcon(icon: Int) {
|
||||||
|
itemList.forEachIndexed { index, item ->
|
||||||
|
if (item.imageResourceId == R.drawable.ic_round_star_filled_24px || item.imageResourceId == R.drawable.ic_round_star_border_24px) {
|
||||||
|
item.imageResourceId = icon
|
||||||
|
this.notifyItemChanged(index)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class ViewHolder internal constructor(itemView: View) : RecyclerView.ViewHolder(itemView),
|
||||||
|
View.OnClickListener, OnLongClickListener {
|
||||||
|
var imageView: ImageView = itemView.findViewById(R.id.buttonImage)
|
||||||
|
var title: TextView = itemView.findViewById(R.id.buttonText)
|
||||||
|
|
||||||
|
init {
|
||||||
|
itemView.setOnClickListener(this)
|
||||||
|
itemView.setOnLongClickListener(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClick(view: View) {
|
||||||
|
if (itemClickListener != null) itemClickListener!!.onBottomSheetItemClick(
|
||||||
|
view,
|
||||||
|
adapterPosition
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLongClick(view: View): Boolean {
|
||||||
|
if (itemClickListener != null) itemClickListener!!.onBottomSheetItemLongClick(
|
||||||
|
view,
|
||||||
|
adapterPosition
|
||||||
|
)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setClickListener(itemClickListener: ItemClickListener?) {
|
||||||
|
this.itemClickListener = itemClickListener
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getContext(): Context {
|
||||||
|
return layoutInflater.context
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ItemClickListener {
|
||||||
|
fun onBottomSheetItemClick(view: View?, position: Int)
|
||||||
|
fun onBottomSheetItemLongClick(view: View?, position: Int)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
package fr.free.nrw.commons.nearby
|
||||||
|
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import fr.free.nrw.commons.R
|
||||||
|
import fr.free.nrw.commons.nearby.model.Description
|
||||||
|
|
||||||
|
class DescriptionAdapter(private val descriptions: List<Description>) :
|
||||||
|
RecyclerView.Adapter<DescriptionAdapter.DescriptionViewHolder>() {
|
||||||
|
|
||||||
|
class DescriptionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
val descTextView: TextView = itemView.findViewById(R.id.descTextView)
|
||||||
|
val userTextView: TextView = itemView.findViewById(R.id.userTextView)
|
||||||
|
val dateTextView: TextView = itemView.findViewById(R.id.dateTextView)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DescriptionViewHolder {
|
||||||
|
val view = LayoutInflater.from(parent.context).inflate(R.layout.layout_wikitalk_item_description, parent, false)
|
||||||
|
return DescriptionViewHolder(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: DescriptionViewHolder, position: Int) {
|
||||||
|
val description = descriptions[position]
|
||||||
|
holder.descTextView.text = description.text
|
||||||
|
holder.userTextView.text = description.user
|
||||||
|
holder.dateTextView.text = description.time
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int {
|
||||||
|
return descriptions.size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -131,6 +131,10 @@ public class NearbyController extends MapController {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getWikiTalk(String s) throws Exception {
|
||||||
|
return nearbyPlaces.getWikiTalk(s);
|
||||||
|
}
|
||||||
|
|
||||||
public static LatLng calculateNorthEast(double latitude, double longitude, double distance) {
|
public static LatLng calculateNorthEast(double latitude, double longitude, double distance) {
|
||||||
double lat1 = Math.toRadians(latitude);
|
double lat1 = Math.toRadians(latitude);
|
||||||
double deltaLat = distance * 0.008;
|
double deltaLat = distance * 0.008;
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,10 @@ public class NearbyPlaces {
|
||||||
customQuery);
|
customQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getWikiTalk(String QID) throws Exception {
|
||||||
|
return okHttpJsonApiClient.getWikidataTalk(QID);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs the Wikidata query to retrieve the KML String
|
* Runs the Wikidata query to retrieve the KML String
|
||||||
*
|
*
|
||||||
|
|
|
||||||
38
app/src/main/java/fr/free/nrw/commons/nearby/TitleAdapter.kt
Normal file
38
app/src/main/java/fr/free/nrw/commons/nearby/TitleAdapter.kt
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
package fr.free.nrw.commons.nearby
|
||||||
|
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import fr.free.nrw.commons.R
|
||||||
|
import fr.free.nrw.commons.nearby.model.Title
|
||||||
|
|
||||||
|
class TitleAdapter(private val titles: List<Title>) :
|
||||||
|
RecyclerView.Adapter<TitleAdapter.TitleViewHolder>() {
|
||||||
|
|
||||||
|
class TitleViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
val titleTextView: TextView = itemView.findViewById(R.id.titleTextView)
|
||||||
|
val descriptionsRecyclerView: RecyclerView = itemView.findViewById(R.id.descriptionsRecyclerView)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TitleViewHolder {
|
||||||
|
val view = LayoutInflater.from(parent.context).inflate(R.layout.layout_wikitalk_item, parent, false)
|
||||||
|
return TitleViewHolder(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: TitleViewHolder, position: Int) {
|
||||||
|
val title = titles[position]
|
||||||
|
holder.titleTextView.text = title.title
|
||||||
|
|
||||||
|
holder.descriptionsRecyclerView.apply {
|
||||||
|
layoutManager = LinearLayoutManager(holder.itemView.context)
|
||||||
|
adapter = DescriptionAdapter(title.descriptions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int {
|
||||||
|
return titles.size
|
||||||
|
}
|
||||||
|
}
|
||||||
142
app/src/main/java/fr/free/nrw/commons/nearby/WikidataFeedback.kt
Normal file
142
app/src/main/java/fr/free/nrw/commons/nearby/WikidataFeedback.kt
Normal file
|
|
@ -0,0 +1,142 @@
|
||||||
|
package fr.free.nrw.commons.nearby
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import fr.free.nrw.commons.databinding.ActivityWikidataFeedbackBinding
|
||||||
|
import fr.free.nrw.commons.nearby.model.Description
|
||||||
|
import fr.free.nrw.commons.nearby.model.Title
|
||||||
|
import fr.free.nrw.commons.theme.BaseActivity
|
||||||
|
import io.reactivex.Observable
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
|
import io.reactivex.schedulers.Schedulers
|
||||||
|
import okhttp3.Call
|
||||||
|
import okhttp3.Callback
|
||||||
|
import okhttp3.FormBody
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.Request
|
||||||
|
import okhttp3.Response
|
||||||
|
import okio.IOException
|
||||||
|
import timber.log.Timber
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
||||||
|
class WikidataFeedback : BaseActivity() {
|
||||||
|
private lateinit var binding: ActivityWikidataFeedbackBinding
|
||||||
|
var place: String = ""
|
||||||
|
var wikidataQId: String = ""
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var nearbyController: NearbyController
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
binding = ActivityWikidataFeedbackBinding.inflate(layoutInflater)
|
||||||
|
setContentView(binding.root)
|
||||||
|
|
||||||
|
place = intent.getStringExtra("place") ?: ""
|
||||||
|
wikidataQId = intent.getStringExtra("qid") ?: ""
|
||||||
|
binding.toolbarBinding.toolbar.title = "Talk:" + wikidataQId
|
||||||
|
binding.textHeader.text = "Write something about the "+"'$place'"+" item. It will be publicly visible."
|
||||||
|
setSupportActionBar(binding.toolbarBinding.toolbar)
|
||||||
|
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
|
||||||
|
getWikidataFeedback(place, wikidataQId)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSupportNavigateUp(): Boolean {
|
||||||
|
onBackPressed()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function starts the Wikidata feedback activity of the selected place
|
||||||
|
* The API returns feedback given by other users
|
||||||
|
*/
|
||||||
|
@SuppressLint("CheckResult")
|
||||||
|
fun getWikidataFeedback(name: String, wikidataQID: String?) {
|
||||||
|
try {
|
||||||
|
val wikiTalkObservable = Observable
|
||||||
|
.fromCallable {
|
||||||
|
nearbyController.getWikiTalk("Talk:"+wikidataQID)
|
||||||
|
}
|
||||||
|
compositeDisposable.add(
|
||||||
|
wikiTalkObservable
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe({ result ->
|
||||||
|
if (result != null) {
|
||||||
|
Timber.tag("PRINT").d("$result")
|
||||||
|
val key = "\"*\":\""
|
||||||
|
var startIndex = result.indexOf(key)
|
||||||
|
startIndex += key.length
|
||||||
|
var endIndex = result.indexOf("\"", startIndex)
|
||||||
|
while (endIndex != -1 && result[endIndex - 1] == '\\') {
|
||||||
|
endIndex = result.indexOf("\"", endIndex + 1)
|
||||||
|
}
|
||||||
|
var value = result.substring(startIndex, endIndex)
|
||||||
|
|
||||||
|
value = value.replace("\\n", "\n").replace("\\\"", "\"")
|
||||||
|
Timber.tag("PRINT").e(value);
|
||||||
|
updateUi(name, value, extractData(value))
|
||||||
|
} else {
|
||||||
|
Timber.d("result is null")
|
||||||
|
Toast.makeText(this, "Failed", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}, { throwable ->
|
||||||
|
Timber.e(throwable, "Error occurred while loading notifications")
|
||||||
|
throwable.printStackTrace()
|
||||||
|
})
|
||||||
|
)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
throw RuntimeException(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateUi(place: String, feedback: String,titles: List<Title> ) {
|
||||||
|
binding.recyclerView.layoutManager = LinearLayoutManager(this)
|
||||||
|
binding.recyclerView.adapter = TitleAdapter(titles)
|
||||||
|
binding.progressBar.visibility = View.GONE
|
||||||
|
binding.activityLayout.visibility = View.VISIBLE
|
||||||
|
binding.descText.text = if (feedback.isNotEmpty()) feedback else "No Feedback"
|
||||||
|
}
|
||||||
|
fun extractData(input: String): List<Title> {
|
||||||
|
val titlePattern = Regex("""==\s*(.*?)\s*==""")
|
||||||
|
val descriptionPattern = Regex("==\\n(.*?\\.)")
|
||||||
|
val userPattern = Regex("""\[\[User:(.*?)\|""")
|
||||||
|
val timestampPattern = Regex("""\d{2}:\d{2}, \d+ \w+ \d{4} \(UTC\)""")
|
||||||
|
|
||||||
|
val titles = titlePattern.findAll(input).map { it.groupValues[1] }.toList()
|
||||||
|
val descriptions = descriptionPattern.findAll(input).map { it.groupValues[1] }.toList()
|
||||||
|
val users = userPattern.findAll(input).map { it.groupValues[1] }.toList()
|
||||||
|
val timestamps = timestampPattern.findAll(input).map { it.value }.toList()
|
||||||
|
|
||||||
|
val groupedDescriptions = mutableListOf<Description>()
|
||||||
|
for (i in 0 until minOf(descriptions.size, users.size, timestamps.size)) {
|
||||||
|
groupedDescriptions.add(Description(descriptions[i], users[i], timestamps[i]))
|
||||||
|
}
|
||||||
|
|
||||||
|
val titleToDescriptions = mutableMapOf<String, MutableList<Description>>()
|
||||||
|
var currentTitle: String? = null
|
||||||
|
|
||||||
|
input.lines().forEach { line ->
|
||||||
|
val titleMatch = titlePattern.matchEntire(line)
|
||||||
|
if (titleMatch != null) {
|
||||||
|
currentTitle = titleMatch.groupValues.getOrNull(1)
|
||||||
|
currentTitle?.let {
|
||||||
|
titleToDescriptions[it] = mutableListOf()
|
||||||
|
}
|
||||||
|
} else if (!currentTitle.isNullOrBlank()) {
|
||||||
|
groupedDescriptions.removeFirstOrNull()
|
||||||
|
?.let { titleToDescriptions[currentTitle]?.add(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return titleToDescriptions.map { (title, descriptions) -> Title(title, descriptions) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -48,6 +48,7 @@ import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.core.content.FileProvider;
|
import androidx.core.content.FileProvider;
|
||||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
||||||
import com.google.android.material.snackbar.Snackbar;
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
|
|
@ -68,9 +69,9 @@ import fr.free.nrw.commons.di.CommonsDaggerSupportFragment;
|
||||||
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
||||||
import fr.free.nrw.commons.location.LocationPermissionsHelper;
|
import fr.free.nrw.commons.location.LocationPermissionsHelper;
|
||||||
import fr.free.nrw.commons.location.LocationPermissionsHelper.LocationPermissionCallback;
|
import fr.free.nrw.commons.location.LocationPermissionsHelper.LocationPermissionCallback;
|
||||||
import fr.free.nrw.commons.location.LatLng;
|
|
||||||
import fr.free.nrw.commons.location.LocationServiceManager;
|
import fr.free.nrw.commons.location.LocationServiceManager;
|
||||||
import fr.free.nrw.commons.location.LocationUpdateListener;
|
import fr.free.nrw.commons.location.LocationUpdateListener;
|
||||||
|
import fr.free.nrw.commons.nearby.BottomSheetAdapter;
|
||||||
import fr.free.nrw.commons.nearby.CheckBoxTriStates;
|
import fr.free.nrw.commons.nearby.CheckBoxTriStates;
|
||||||
import fr.free.nrw.commons.nearby.Label;
|
import fr.free.nrw.commons.nearby.Label;
|
||||||
import fr.free.nrw.commons.nearby.MarkerPlaceGroup;
|
import fr.free.nrw.commons.nearby.MarkerPlaceGroup;
|
||||||
|
|
@ -78,8 +79,10 @@ import fr.free.nrw.commons.nearby.NearbyController;
|
||||||
import fr.free.nrw.commons.nearby.NearbyFilterSearchRecyclerViewAdapter;
|
import fr.free.nrw.commons.nearby.NearbyFilterSearchRecyclerViewAdapter;
|
||||||
import fr.free.nrw.commons.nearby.NearbyFilterState;
|
import fr.free.nrw.commons.nearby.NearbyFilterState;
|
||||||
import fr.free.nrw.commons.nearby.Place;
|
import fr.free.nrw.commons.nearby.Place;
|
||||||
|
import fr.free.nrw.commons.nearby.WikidataFeedback;
|
||||||
import fr.free.nrw.commons.nearby.contract.NearbyParentFragmentContract;
|
import fr.free.nrw.commons.nearby.contract.NearbyParentFragmentContract;
|
||||||
import fr.free.nrw.commons.nearby.fragments.AdvanceQueryFragment.Callback;
|
import fr.free.nrw.commons.nearby.fragments.AdvanceQueryFragment.Callback;
|
||||||
|
import fr.free.nrw.commons.nearby.model.BottomSheetItem;
|
||||||
import fr.free.nrw.commons.nearby.presenter.NearbyParentFragmentPresenter;
|
import fr.free.nrw.commons.nearby.presenter.NearbyParentFragmentPresenter;
|
||||||
import fr.free.nrw.commons.upload.FileUtils;
|
import fr.free.nrw.commons.upload.FileUtils;
|
||||||
import fr.free.nrw.commons.utils.DialogUtil;
|
import fr.free.nrw.commons.utils.DialogUtil;
|
||||||
|
|
@ -132,7 +135,7 @@ import timber.log.Timber;
|
||||||
public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
implements NearbyParentFragmentContract.View,
|
implements NearbyParentFragmentContract.View,
|
||||||
WikidataEditListener.WikidataP18EditListener, LocationUpdateListener,
|
WikidataEditListener.WikidataP18EditListener, LocationUpdateListener,
|
||||||
LocationPermissionCallback {
|
LocationPermissionCallback, BottomSheetAdapter.ItemClickListener {
|
||||||
|
|
||||||
|
|
||||||
FragmentNearbyParentBinding binding;
|
FragmentNearbyParentBinding binding;
|
||||||
|
|
@ -190,6 +193,9 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
private NearbyParentFragmentInstanceReadyCallback nearbyParentFragmentInstanceReadyCallback;
|
private NearbyParentFragmentInstanceReadyCallback nearbyParentFragmentInstanceReadyCallback;
|
||||||
private boolean isAdvancedQueryFragmentVisible = false;
|
private boolean isAdvancedQueryFragmentVisible = false;
|
||||||
private Place nearestPlace;
|
private Place nearestPlace;
|
||||||
|
private GridLayoutManager gridLayoutManager;
|
||||||
|
private List<BottomSheetItem> dataList;
|
||||||
|
private BottomSheetAdapter bottomSheetAdapter;
|
||||||
private ActivityResultLauncher<String[]> inAppCameraLocationPermissionLauncher = registerForActivityResult(
|
private ActivityResultLauncher<String[]> inAppCameraLocationPermissionLauncher = registerForActivityResult(
|
||||||
new ActivityResultContracts.RequestMultiplePermissions(),
|
new ActivityResultContracts.RequestMultiplePermissions(),
|
||||||
new ActivityResultCallback<Map<String, Boolean>>() {
|
new ActivityResultCallback<Map<String, Boolean>>() {
|
||||||
|
|
@ -650,7 +656,6 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
initBottomSheets();
|
initBottomSheets();
|
||||||
loadAnimations();
|
loadAnimations();
|
||||||
setBottomSheetCallbacks();
|
setBottomSheetCallbacks();
|
||||||
decideButtonVisibilities();
|
|
||||||
addActionToTitle();
|
addActionToTitle();
|
||||||
if (!Utils.isMonumentsEnabled(new Date())) {
|
if (!Utils.isMonumentsEnabled(new Date())) {
|
||||||
NearbyFilterState.setWlmSelected(false);
|
NearbyFilterState.setWlmSelected(false);
|
||||||
|
|
@ -674,6 +679,15 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
bottomSheetListBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
|
bottomSheetListBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getSpanCount() {
|
||||||
|
int orientation = getResources().getConfiguration().orientation;
|
||||||
|
if (bottomSheetAdapter != null){
|
||||||
|
return (orientation == Configuration.ORIENTATION_PORTRAIT) ? 3 : bottomSheetAdapter.getItemCount();
|
||||||
|
}else {
|
||||||
|
return (orientation == Configuration.ORIENTATION_PORTRAIT) ? 3 : 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void initNearbyFilter() {
|
public void initNearbyFilter() {
|
||||||
binding.nearbyFilterList.getRoot().setVisibility(View.GONE);
|
binding.nearbyFilterList.getRoot().setVisibility(View.GONE);
|
||||||
hideBottomSheet();
|
hideBottomSheet();
|
||||||
|
|
@ -898,20 +912,6 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
rotate_backward = AnimationUtils.loadAnimation(getActivity(), R.anim.rotate_backward);
|
rotate_backward = AnimationUtils.loadAnimation(getActivity(), R.anim.rotate_backward);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Fits buttons according to our layout
|
|
||||||
*/
|
|
||||||
private void decideButtonVisibilities() {
|
|
||||||
// Remove button text if they exceed 1 line or if internal layout has not been built
|
|
||||||
// Only need to check for directions button because it is the longest
|
|
||||||
if ( binding.bottomSheetDetails.directionsButtonText.getLineCount() > 1 || binding.bottomSheetDetails.directionsButtonText.getLineCount() == 0) {
|
|
||||||
binding.bottomSheetDetails.wikipediaButtonText.setVisibility(View.GONE);
|
|
||||||
binding.bottomSheetDetails.wikidataButtonText.setVisibility(View.GONE);
|
|
||||||
binding.bottomSheetDetails.commonsButtonText.setVisibility(View.GONE);
|
|
||||||
binding.bottomSheetDetails.directionsButtonText.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
@ -2006,50 +2006,33 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
*/
|
*/
|
||||||
private void passInfoToSheet(final Place place) {
|
private void passInfoToSheet(final Place place) {
|
||||||
selectedPlace = place;
|
selectedPlace = place;
|
||||||
|
dataList = new ArrayList<>();
|
||||||
|
// TODO: Decide button text for fitting in the screen
|
||||||
|
dataList.add(new BottomSheetItem(R.drawable.ic_round_star_border_24px, ""));
|
||||||
|
dataList.add(new BottomSheetItem(R.drawable.ic_directions_black_24dp,
|
||||||
|
getResources().getString(R.string.nearby_directions)));
|
||||||
|
if (place.hasWikidataLink()) {
|
||||||
|
dataList.add(new BottomSheetItem(R.drawable.ic_wikidata_logo_24dp,
|
||||||
|
getResources().getString(R.string.nearby_wikidata)));
|
||||||
|
}
|
||||||
|
dataList.add(new BottomSheetItem(R.drawable.ic_feedback_black_24dp,
|
||||||
|
getResources().getString(R.string.nearby_wikitalk)));
|
||||||
|
if (place.hasWikipediaLink()) {
|
||||||
|
dataList.add(new BottomSheetItem(R.drawable.ic_wikipedia_logo_24dp,
|
||||||
|
getResources().getString(R.string.nearby_wikipedia)));
|
||||||
|
}
|
||||||
|
if (selectedPlace.hasCommonsLink()) {
|
||||||
|
dataList.add(new BottomSheetItem(R.drawable.ic_commons_icon_vector,
|
||||||
|
getResources().getString(R.string.nearby_commons)));
|
||||||
|
}
|
||||||
|
int spanCount = getSpanCount();
|
||||||
|
gridLayoutManager = new GridLayoutManager(this.getContext(), spanCount);
|
||||||
|
binding.bottomSheetDetails.bottomSheetRecyclerView.setLayoutManager(gridLayoutManager);
|
||||||
|
bottomSheetAdapter = new BottomSheetAdapter(this.getContext(), dataList);
|
||||||
|
bottomSheetAdapter.setClickListener(this);
|
||||||
|
binding.bottomSheetDetails.bottomSheetRecyclerView.setAdapter(bottomSheetAdapter);
|
||||||
updateBookmarkButtonImage(selectedPlace);
|
updateBookmarkButtonImage(selectedPlace);
|
||||||
|
|
||||||
binding.bottomSheetDetails.bookmarkButton.setOnClickListener(view -> {
|
|
||||||
final boolean isBookmarked = bookmarkLocationDao.updateBookmarkLocation(selectedPlace);
|
|
||||||
updateBookmarkButtonImage(selectedPlace);
|
|
||||||
updateMarker(isBookmarked, selectedPlace, locationManager.getLastLocation());
|
|
||||||
binding.map.invalidate();
|
|
||||||
});
|
|
||||||
binding.bottomSheetDetails.bookmarkButton.setOnLongClickListener(view -> {
|
|
||||||
Toast.makeText(getContext(), R.string.menu_bookmark, Toast.LENGTH_SHORT).show();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
binding.bottomSheetDetails.wikipediaButton.setVisibility(place.hasWikipediaLink() ? View.VISIBLE : View.GONE);
|
|
||||||
binding.bottomSheetDetails.wikipediaButton.setOnClickListener(
|
|
||||||
view -> Utils.handleWebUrl(getContext(), selectedPlace.siteLinks.getWikipediaLink()));
|
|
||||||
binding.bottomSheetDetails.wikipediaButton.setOnLongClickListener(view -> {
|
|
||||||
Toast.makeText(getContext(), R.string.nearby_wikipedia, Toast.LENGTH_SHORT).show();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
binding.bottomSheetDetails.wikidataButton.setVisibility(place.hasWikidataLink() ? View.VISIBLE : View.GONE);
|
|
||||||
binding.bottomSheetDetails.wikidataButton.setOnClickListener(
|
|
||||||
view -> Utils.handleWebUrl(getContext(), selectedPlace.siteLinks.getWikidataLink()));
|
|
||||||
binding.bottomSheetDetails.wikidataButton.setOnLongClickListener(view -> {
|
|
||||||
Toast.makeText(getContext(), R.string.nearby_wikidata, Toast.LENGTH_SHORT).show();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
binding.bottomSheetDetails.directionsButton.setOnClickListener(view -> Utils.handleGeoCoordinates(getActivity(),
|
|
||||||
selectedPlace.getLocation()));
|
|
||||||
binding.bottomSheetDetails.directionsButton.setOnLongClickListener(view -> {
|
|
||||||
Toast.makeText(getContext(), R.string.nearby_directions, Toast.LENGTH_SHORT).show();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
binding.bottomSheetDetails.commonsButton.setVisibility(selectedPlace.hasCommonsLink() ? View.VISIBLE : View.GONE);
|
|
||||||
binding.bottomSheetDetails.commonsButton.setOnClickListener(
|
|
||||||
view -> Utils.handleWebUrl(getContext(), selectedPlace.siteLinks.getCommonsLink()));
|
|
||||||
binding.bottomSheetDetails.commonsButton.setOnLongClickListener(view -> {
|
|
||||||
Toast.makeText(getContext(), R.string.nearby_commons, Toast.LENGTH_SHORT).show();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
binding.bottomSheetDetails.icon.setImageResource(selectedPlace.getLabel().getIcon());
|
binding.bottomSheetDetails.icon.setImageResource(selectedPlace.getLabel().getIcon());
|
||||||
|
|
||||||
binding.bottomSheetDetails.title.setText(selectedPlace.name);
|
binding.bottomSheetDetails.title.setText(selectedPlace.name);
|
||||||
|
|
@ -2101,9 +2084,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
} else {
|
} else {
|
||||||
bookmarkIcon = R.drawable.ic_round_star_border_24px;
|
bookmarkIcon = R.drawable.ic_round_star_border_24px;
|
||||||
}
|
}
|
||||||
if ( binding.bottomSheetDetails.bookmarkButtonImage != null) {
|
bottomSheetAdapter.updateBookmarkIcon(bookmarkIcon);
|
||||||
binding.bottomSheetDetails.bookmarkButtonImage.setImageResource(bookmarkIcon);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -2281,6 +2262,77 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
binding.map.getController().animateTo(geoPoint);
|
binding.map.getController().animateTo(geoPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBottomSheetItemClick(@Nullable View view, int position) {
|
||||||
|
BottomSheetItem item = dataList.get(position);
|
||||||
|
final boolean isBookmarked = bookmarkLocationDao.updateBookmarkLocation(selectedPlace);
|
||||||
|
switch (item.getImageResourceId()) {
|
||||||
|
case R.drawable.ic_round_star_border_24px:
|
||||||
|
updateBookmarkButtonImage(selectedPlace);
|
||||||
|
updateMarker(isBookmarked, selectedPlace, locationManager.getLastLocation());
|
||||||
|
binding.map.invalidate();
|
||||||
|
break;
|
||||||
|
case R.drawable.ic_round_star_filled_24px:
|
||||||
|
updateBookmarkButtonImage(selectedPlace);
|
||||||
|
updateMarker(isBookmarked, selectedPlace, locationManager.getLastLocation());
|
||||||
|
binding.map.invalidate();
|
||||||
|
break;
|
||||||
|
case R.drawable.ic_directions_black_24dp:
|
||||||
|
Utils.handleGeoCoordinates(this.getContext(), selectedPlace.getLocation());
|
||||||
|
break;
|
||||||
|
case R.drawable.ic_wikidata_logo_24dp:
|
||||||
|
Utils.handleWebUrl(this.getContext(), selectedPlace.siteLinks.getWikidataLink());
|
||||||
|
break;
|
||||||
|
case R.drawable.ic_feedback_black_24dp:
|
||||||
|
Intent intent = new Intent(this.getContext(), WikidataFeedback.class);
|
||||||
|
intent.putExtra("place", selectedPlace.name);
|
||||||
|
intent.putExtra("qid", selectedPlace.getWikiDataEntityId());
|
||||||
|
startActivity(intent);
|
||||||
|
break;
|
||||||
|
case R.drawable.ic_wikipedia_logo_24dp:
|
||||||
|
Utils.handleWebUrl(this.getContext(), selectedPlace.siteLinks.getWikipediaLink());
|
||||||
|
break;
|
||||||
|
case R.drawable.ic_commons_icon_vector:
|
||||||
|
Utils.handleWebUrl(this.getContext(), selectedPlace.siteLinks.getCommonsLink());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBottomSheetItemLongClick(@Nullable View view, int position) {
|
||||||
|
BottomSheetItem item = dataList.get(position);
|
||||||
|
String message;
|
||||||
|
switch (item.getImageResourceId()) {
|
||||||
|
case R.drawable.ic_round_star_border_24px:
|
||||||
|
message = getString(R.string.menu_bookmark);
|
||||||
|
break;
|
||||||
|
case R.drawable.ic_round_star_filled_24px:
|
||||||
|
message = getString(R.string.menu_bookmark);
|
||||||
|
break;
|
||||||
|
case R.drawable.ic_directions_black_24dp:
|
||||||
|
message = getString(R.string.nearby_directions);
|
||||||
|
break;
|
||||||
|
case R.drawable.ic_wikidata_logo_24dp:
|
||||||
|
message = getString(R.string.nearby_wikidata);
|
||||||
|
break;
|
||||||
|
case R.drawable.ic_feedback_black_24dp:
|
||||||
|
message = getString(R.string.nearby_wikitalk);
|
||||||
|
break;
|
||||||
|
case R.drawable.ic_wikipedia_logo_24dp:
|
||||||
|
message = getString(R.string.nearby_wikipedia);
|
||||||
|
break;
|
||||||
|
case R.drawable.ic_commons_icon_vector:
|
||||||
|
message = getString(R.string.nearby_commons);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
message = "Long click";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Toast.makeText(this.getContext(), message, Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
|
||||||
public interface NearbyParentFragmentInstanceReadyCallback {
|
public interface NearbyParentFragmentInstanceReadyCallback {
|
||||||
|
|
||||||
void onReady();
|
void onReady();
|
||||||
|
|
@ -2298,9 +2350,12 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
rlBottomSheetLayoutParams.height =
|
rlBottomSheetLayoutParams.height =
|
||||||
getActivity().getWindowManager().getDefaultDisplay().getHeight() / 16 * 9;
|
getActivity().getWindowManager().getDefaultDisplay().getHeight() / 16 * 9;
|
||||||
binding.bottomSheetNearby.bottomSheet.setLayoutParams(rlBottomSheetLayoutParams);
|
binding.bottomSheetNearby.bottomSheet.setLayoutParams(rlBottomSheetLayoutParams);
|
||||||
|
int spanCount = getSpanCount();
|
||||||
|
if (gridLayoutManager != null) {
|
||||||
|
gridLayoutManager.setSpanCount(spanCount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void onLearnMoreClicked() {
|
public void onLearnMoreClicked() {
|
||||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||||
intent.setData(Uri.parse(WLM_URL));
|
intent.setData(Uri.parse(WLM_URL));
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
package fr.free.nrw.commons.nearby.model
|
||||||
|
|
||||||
|
class BottomSheetItem(var imageResourceId: Int, val title: String)
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
package fr.free.nrw.commons.nearby.model
|
||||||
|
|
||||||
|
data class Description(
|
||||||
|
val text: String,
|
||||||
|
val user: String,
|
||||||
|
val time: String
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Title(
|
||||||
|
val title: String,
|
||||||
|
val descriptions: List<Description>
|
||||||
|
)
|
||||||
132
app/src/main/res/layout/activity_wikidata_feedback.xml
Normal file
132
app/src/main/res/layout/activity_wikidata_feedback.xml
Normal file
|
|
@ -0,0 +1,132 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".nearby.WikidataFeedback">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/toolbarLayout"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/toolbarBinding"
|
||||||
|
layout="@layout/toolbar" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progress_bar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:id="@+id/activity_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:visibility="visible"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/toolbarLayout">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/recyclerView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/textHeader"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/currentTextLabel" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:id="@+id/textHeader"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:text="Write something about the 'GS1 Japan' item. It will be publicly visible."
|
||||||
|
android:textSize="@dimen/normal_text"
|
||||||
|
android:visibility="visible"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/descriptionEditText"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatEditText
|
||||||
|
android:id="@+id/subjectEditText"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:hint="Subject"
|
||||||
|
android:singleLine="false"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/textHeader" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatEditText
|
||||||
|
android:id="@+id/descriptionEditText"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:hint="Description"
|
||||||
|
android:singleLine="false"
|
||||||
|
android:visibility="visible"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/appCompatButton"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/descText"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:inputType="textMultiLine"
|
||||||
|
android:text="Discussion"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/currentTextLabel" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
|
android:id="@+id/appCompatButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:text="SEND"
|
||||||
|
android:visibility="visible"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="@+id/textHeader"
|
||||||
|
app:layout_constraintHorizontal_bias="1.0"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/textHeader" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:id="@+id/currentTextLabel"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:text="Current talk page:"
|
||||||
|
android:textSize="@dimen/heading_text_size"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
@ -53,169 +53,21 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/tiny_height"
|
android:layout_height="@dimen/tiny_height"
|
||||||
android:layout_marginTop="@dimen/small_height"
|
android:layout_marginTop="@dimen/small_height"
|
||||||
android:layout_marginBottom="@dimen/activity_margin_horizontal"
|
android:layout_marginBottom="@dimen/activity_margin_horizontal"
|
||||||
android:background="@android:color/darker_gray"/>
|
android:background="@android:color/darker_gray" />
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
>
|
|
||||||
|
|
||||||
<LinearLayout
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/bookmarkButton"
|
android:id="@+id/bottom_sheet_recycler_view"
|
||||||
android:layout_width="@dimen/dimen_0"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content" />
|
||||||
android:layout_weight="1"
|
|
||||||
android:padding="@dimen/standard_gap"
|
|
||||||
android:clickable="true"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:background="@drawable/button_background_selector"
|
|
||||||
>
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/bookmarkButtonImage"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
app:srcCompat="@drawable/ic_round_star_border_24px"
|
|
||||||
android:tint="?attr/rowButtonColor"/>
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:id="@+id/bookmarkButtonText"
|
|
||||||
android:paddingTop="@dimen/activity_margin_horizontal"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:text="CAMERA"
|
|
||||||
android:visibility="gone"
|
|
||||||
/>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/directionsButton"
|
|
||||||
android:layout_width="@dimen/dimen_0"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:padding="@dimen/standard_gap"
|
|
||||||
android:clickable="true"
|
|
||||||
android:background="@drawable/button_background_selector"
|
|
||||||
android:orientation="vertical"
|
|
||||||
>
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:duplicateParentState="true"
|
|
||||||
app:srcCompat="@drawable/ic_directions_black_24dp"
|
|
||||||
android:tint="?attr/rowButtonColor"
|
|
||||||
/>
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:id="@+id/directionsButtonText"
|
|
||||||
android:paddingTop="@dimen/activity_margin_horizontal"
|
|
||||||
android:duplicateParentState="true"
|
|
||||||
android:textColor="@color/text_color_selector"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:text="@string/nearby_directions"
|
|
||||||
android:textAllCaps="true"
|
|
||||||
/>
|
|
||||||
</LinearLayout>
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/wikidataButton"
|
|
||||||
android:layout_width="@dimen/dimen_0"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:padding="@dimen/standard_gap"
|
|
||||||
android:clickable="true"
|
|
||||||
android:background="@drawable/button_background_selector"
|
|
||||||
android:orientation="vertical"
|
|
||||||
>
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:duplicateParentState="true"
|
|
||||||
app:srcCompat="@drawable/ic_wikidata_logo_24dp"
|
|
||||||
android:tint="?attr/rowButtonColor"/>
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:id="@+id/wikidataButtonText"
|
|
||||||
android:paddingTop="@dimen/activity_margin_horizontal"
|
|
||||||
android:duplicateParentState="true"
|
|
||||||
android:textColor="@color/text_color_selector"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:text="@string/nearby_wikidata"
|
|
||||||
android:textAllCaps="true"
|
|
||||||
/>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/wikipediaButton"
|
|
||||||
android:layout_width="@dimen/dimen_0"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:padding="@dimen/standard_gap"
|
|
||||||
android:clickable="true"
|
|
||||||
android:background="@drawable/button_background_selector"
|
|
||||||
android:orientation="vertical"
|
|
||||||
>
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:duplicateParentState="true"
|
|
||||||
app:srcCompat="@drawable/ic_wikipedia_logo_24dp"
|
|
||||||
android:tint="?attr/rowButtonColor"
|
|
||||||
/>
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:id="@+id/wikipediaButtonText"
|
|
||||||
android:paddingTop="@dimen/activity_margin_horizontal"
|
|
||||||
android:duplicateParentState="true"
|
|
||||||
android:textColor="@color/text_color_selector"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:text="@string/nearby_wikipedia"
|
|
||||||
android:textAllCaps="true"
|
|
||||||
/>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/commonsButton"
|
|
||||||
android:layout_width="@dimen/dimen_0"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:padding="@dimen/standard_gap"
|
|
||||||
android:clickable="true"
|
|
||||||
android:background="@drawable/button_background_selector"
|
|
||||||
android:orientation="vertical"
|
|
||||||
>
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:duplicateParentState="true"
|
|
||||||
app:srcCompat="@drawable/ic_commons_icon_vector"
|
|
||||||
/>
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:id="@+id/commonsButtonText"
|
|
||||||
android:paddingTop="@dimen/activity_margin_horizontal"
|
|
||||||
android:duplicateParentState="true"
|
|
||||||
android:textColor="@color/text_color_selector"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:text="@string/nearby_commons"
|
|
||||||
android:textAllCaps="true"
|
|
||||||
/>
|
|
||||||
</LinearLayout>
|
|
||||||
</LinearLayout>
|
|
||||||
<View
|
<View
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/tiny_height"
|
android:layout_height="@dimen/tiny_height"
|
||||||
android:layout_marginTop="@dimen/small_height"
|
android:layout_marginTop="@dimen/small_height"
|
||||||
android:layout_marginBottom="@dimen/activity_margin_horizontal"
|
android:layout_marginBottom="@dimen/activity_margin_horizontal"
|
||||||
android:background="@android:color/darker_gray"/>
|
android:background="@android:color/darker_gray" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/description"
|
android:id="@+id/description"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
||||||
27
app/src/main/res/layout/bottom_sheet_item_layout.xml
Normal file
27
app/src/main/res/layout/bottom_sheet_item_layout.xml
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/bookmarkButton"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_columnWeight="1"
|
||||||
|
android:background="@drawable/button_background_selector"
|
||||||
|
android:clickable="true"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="@dimen/standard_gap">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/buttonImage"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:tint="?attr/rowButtonColor" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/buttonText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:paddingTop="@dimen/activity_margin_horizontal"
|
||||||
|
android:text="CAMERA"
|
||||||
|
android:visibility="gone" />
|
||||||
|
</LinearLayout>
|
||||||
22
app/src/main/res/layout/layout_wikitalk_item.xml
Normal file
22
app/src/main/res/layout/layout_wikitalk_item.xml
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/titleTextView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingTop="@dimen/dimen_10"
|
||||||
|
android:paddingBottom="8dp"
|
||||||
|
android:textSize="20sp"
|
||||||
|
android:text="Title"/>
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/descriptionsRecyclerView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
35
app/src/main/res/layout/layout_wikitalk_item_description.xml
Normal file
35
app/src/main/res/layout/layout_wikitalk_item_description.xml
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="2dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/descTextView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="TextView"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/userTextView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="TextView" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/dateTextView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="TextView" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
@ -818,4 +818,5 @@ Upload your first media by tapping on the add button.</string>
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="multiple_files_depiction">Please remember that all images in a multi-upload get the same categories and depictions. If the images do not share depictions and categories, please perform several separate uploads.</string>
|
<string name="multiple_files_depiction">Please remember that all images in a multi-upload get the same categories and depictions. If the images do not share depictions and categories, please perform several separate uploads.</string>
|
||||||
<string name="multiple_files_depiction_header">Note about multi-uploads</string>
|
<string name="multiple_files_depiction_header">Note about multi-uploads</string>
|
||||||
|
<string name="nearby_wikitalk">wikitalk</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue