Skip to content

Commit

Permalink
Merge pull request #7 from pk-218/dev
Browse files Browse the repository at this point in the history
Final phase changes
  • Loading branch information
sans2801 authored Mar 27, 2022
2 parents 96686c1 + 663ac19 commit 693d72a
Show file tree
Hide file tree
Showing 79 changed files with 1,940 additions and 159 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/misc.xml
/.idea/assetWizardSettings.xml
/.idea/misc.xml
.DS_Store
/build
/captures
Expand Down
2 changes: 1 addition & 1 deletion .idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 0 additions & 20 deletions .idea/misc.xml

This file was deleted.

2 changes: 1 addition & 1 deletion .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'androidx.navigation.safeargs.kotlin'
id 'kotlin-kapt'
id 'dagger.hilt.android.plugin'
}

android {
Expand Down Expand Up @@ -45,7 +48,31 @@ dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2'
implementation 'androidx.navigation:navigation-ui-ktx:2.4.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1'

// Preferences DataStore
implementation "androidx.datastore:datastore-preferences:1.0.0"

// Dagger-Hilt
implementation "com.google.dagger:hilt-android:2.38.1"
implementation 'androidx.room:room-common:2.3.0'
kapt "com.google.dagger:hilt-compiler:2.38.1"
implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03"
kapt "androidx.hilt:hilt-compiler:1.0.0"

implementation 'androidx.legacy:legacy-support-v4:1.0.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

//Room
implementation "androidx.room:room-runtime:2.2.5"
kapt "androidx.room:room-compiler:2.2.5"
implementation "androidx.room:room-ktx:2.2.5"

//Glide
implementation 'com.github.bumptech.glide:glide:4.4.0'

// Splash screen
implementation 'androidx.core:core-splashscreen:1.0.0-beta02'

}
12 changes: 9 additions & 3 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,20 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />


<application
android:name=".KnoxApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:icon="@mipmap/ic_knox_logo"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:roundIcon="@mipmap/ic_knox_logo"
android:supportsRtl="true"
android:theme="@style/Theme.Knox">
android:theme="@style/Theme.App.Starting">
<activity
android:name=".MainActivity"
android:exported="true"
Expand Down
Binary file added app/src/main/ic_knox_logo-playstore.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
181 changes: 172 additions & 9 deletions app/src/main/java/tech/kotlinx/knox/ChatFragment.kt
Original file line number Diff line number Diff line change
@@ -1,26 +1,189 @@
package tech.kotlinx.knox

import android.app.Activity.RESULT_OK
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.util.Log
import android.view.*
import android.widget.Toast
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import android.view.inputmethod.InputMethodManager
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.loader.content.CursorLoader
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import dagger.hilt.android.AndroidEntryPoint
import tech.kotlinx.knox.adapter.MessageAdapter
import tech.kotlinx.knox.data.model.Datasource
import tech.kotlinx.knox.databinding.FragmentChatBinding
import tech.kotlinx.knox.ui.viewmodels.ChatViewModel
import tech.kotlinx.knox.util.RealPath
import java.io.File


@AndroidEntryPoint
class ChatFragment : Fragment() {

private val viewModel: ChatViewModel by viewModels()
private var myPort = 5000
private var myUserName: String? = ""
private val args by navArgs<ChatFragmentArgs>()

private var _binding: FragmentChatBinding? = null
private val binding get() = _binding!!

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
): View {

_binding = FragmentChatBinding.inflate(inflater, container, false)
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

//End Chat
binding.endChat.setOnClickListener(){
Toast.makeText(context, "Chat Ended", Toast.LENGTH_SHORT).show()
findNavController().navigate(
R.id.action_ChatFragment_to_ConnectionDetailsFragment,
)
}




// get receiver IP address and port from args
Log.d("ChatFragmentArgs", args.senderUserName + args.receiverIP + ":" + args.receiverPort.toString())

// render messages
binding.messageView.adapter = context?.let {
MessageAdapter(it, viewModel.messages.value!!)
}

viewModel.userName.observe(viewLifecycleOwner) {username ->
binding.name.text = username
}

viewModel.status.observe(viewLifecycleOwner) {status ->
binding.status.text = status
}
val a = "@" + args.senderUserName
viewModel.messages.observe(viewLifecycleOwner) { newMessages ->
with(binding) {
messageView.adapter?.notifyItemInserted(newMessages.size - 1)
messageView.scrollToPosition(newMessages.size - 1)
}
}

//start file server
// start chat server
viewModel.startServer(myPort)

viewModel.sendMessage(a, args.receiverIP, args.receiverPort)

//start file server
viewModel.startFileServer(myPort) // 1

binding.buttonChatboxSend.setOnClickListener {
if (binding.edittextChatbox.text.isNotBlank()) {
viewModel.sendMessage(
binding.edittextChatbox.text.toString(),
args.receiverIP,
args.receiverPort
)
binding.edittextChatbox.text.clear()
val imm =
requireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(view.windowToken, 0)
}
}

val view = inflater.inflate(R.layout.fragment_chat, container, false)
val messages = Datasource().loadMessages()
val recyclerView=view.findViewById<RecyclerView>(R.id.message_view)
recyclerView.adapter= context?.let { MessageAdapter(it, messages) }

return view
//file attachment send

binding.fileSend.setOnClickListener {
Log.d("File send", "clicked on file send")
val intent = Intent()
.setType("*/*")
.setAction(Intent.ACTION_GET_CONTENT)

startActivityForResult(Intent.createChooser(intent, "Select a file"), 111)
}
}

override fun onPause() {
super.onPause()
viewModel.sendMessage("Offline", args.receiverIP, args.receiverPort)
}

override fun onResume() {
super.onResume()
viewModel.sendMessage("Online", args.receiverIP, args.receiverPort)
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)

if (requestCode == 111 && resultCode == RESULT_OK) {
val selectedFile = data?.data //The uri with the location of the file
Log.d("URI of Selected File", selectedFile.toString())
//get real path from URI
val realPath = RealPath()
val filePath = realPath.getPathFromUri(context, selectedFile)
//send file to receiver
if (selectedFile != null) {
Log.d("Path of file ",filePath.toString())
if (filePath != null) {
viewModel.sendFile( // 2
filePath,
args.receiverIP,
args.receiverPort
)
}
}

}
}






// Function for displaying an AlertDialogue for choosing an image
// private fun selectImage() {
// val choice = arrayOf<CharSequence>("Take Photo", "Choose from Gallery", "Cancel")
// val myAlertDialog: AlertDialog.Builder = AlertDialog.Builder(this)
// myAlertDialog.setTitle("Select Image")
// myAlertDialog.setItems(choice, DialogInterface.OnClickListener { dialog, item ->
// when {
// // Select "Choose from Gallery" to pick image from gallery
// choice[item] == "Choose from Gallery" -> {
// val pickFromGallery = Intent(Intent.ACTION_GET_CONTENT, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
// pickFromGallery.type = "/image"
// startActivityForResult(pickFromGallery, 1)
// }
// // Select "Take Photo" to take a photo
// choice[item] == "Take Photo" -> {
// val cameraPicture = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
// startActivityForResult(cameraPicture, 0)
// }
// // Select "Cancel" to cancel the task
// choice[item] == "Cancel" -> {
// myAlertDialog.dismiss()
// }
// }
// })
// myAlertDialog.show()
// }




}
29 changes: 21 additions & 8 deletions app/src/main/java/tech/kotlinx/knox/ConnectionDetailsFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,23 @@ import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import dagger.hilt.android.AndroidEntryPoint
import tech.kotlinx.knox.databinding.FragmentConnectionDetailsBinding
import java.net.NetworkInterface
import java.util.*


/**
* A simple [Fragment] subclass as the second destination in the navigation.
*/
@AndroidEntryPoint
class ConnectionDetailsFragment : Fragment() {

private var _binding: FragmentConnectionDetailsBinding? = null
private val args by navArgs<ConnectionDetailsFragmentArgs>()

// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!

override fun onCreateView(
Expand All @@ -40,8 +41,12 @@ class ConnectionDetailsFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

Log.d("FragmentArgs", args.userName)
Toast.makeText(context, "Welcome ${args.userName}", Toast.LENGTH_SHORT).show()

var userIpAddress: String? = "0.0.0.0"
val connectivityManager: ConnectivityManager = context?.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val connectivityManager: ConnectivityManager =
context?.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
@Suppress("DEPRECATION")
when (connectivityManager.activeNetworkInfo?.type) {
ConnectivityManager.TYPE_WIFI -> userIpAddress = getWifiIpAddress()
Expand All @@ -50,7 +55,15 @@ class ConnectionDetailsFragment : Fragment() {
binding.senderIpAddressField.setText(userIpAddress)

binding.enterChatButton.setOnClickListener {
findNavController().navigate(R.id.action_SecondFragment_to_FirstFragment)
val bundle = bundleOf(
"receiverIP" to binding.receiverIpAddressText.text.toString(),
"receiverPort" to 5000,
"senderUserName" to args.userName
)
findNavController().navigate(
R.id.action_ConnectionDetailsFragment_to_ChatFragment,
bundle
)
}
}

Expand Down Expand Up @@ -83,7 +96,7 @@ class ConnectionDetailsFragment : Fragment() {
if (delimiter < 0)
result.uppercase(Locale.getDefault())
else
result.substring(0, delimiter).uppercase(Locale.getDefault());
result.substring(0, delimiter).uppercase(Locale.getDefault())
}
}
}
Expand Down
Loading

0 comments on commit 693d72a

Please sign in to comment.