how can I solve edittext recursion problem? - kotlin

I was trying to implement live typeface change's in the edittextview
based on markdown syntax
and the first code I do was
my_edit_text_view.text = makeMDStyleSpannable(my_edit_text_view.text)//returns spannableString
but no luck since it is not invoking every time when text is changed
so I gave another try which is creating listener and testing things are working properly before I jump
my_edit_text_view.text = doOnTextChanged { it, start, count,after ->
if (it != null) {
if(it.isNotEmpty()){
Toast.makeText(this, (makeMDStyleSpannable(it)), Toast.LENGTH_SHORT).show()
}else if(it.isNullOrEmpty()){
}
}
}
as result it worked on another TOAST
However, here's the real recurring happened
my_edit_text_view.text = doOnTextChanged { it, start, count,after ->
if (it != null) {
if(it.isNotEmpty()){
my_edit_text_view.text = (makeMDStyleSpannable(it)
}else if(it.isNullOrEmpty()){
}
}
}
umm, what actually happening is while there is external text change(keyboard) on the edittext it calls makeMDStyleSpannable and this apply internal change then again and again it will call doOnTextChanged, Finally crashes.
How could I solve this problem?
keyboard(onText added[external]) => startThelistner => makeMDStyleSpannable[in]
/\ ||
||=====[infinite]=======
thanks

You can solve it by adding a boolean to check if text is changed by user or the code.
val shouldIgnoreChange = false
my_edit_text_view.text = doOnTextChanged { it, start, count,after ->
if (it != null) {
if(it.isNotEmpty()){
if(!shouldIgnoreChange){
shouldIgnoreChange = true
my_edit_text_view.text = (makeMDStyleSpannable(it)
shouldIgnoreChange = false
}
}else if(it.isNullOrEmpty()){
}
}
}

Related

Executing a callback only when reaching a certain state without user interactions

Our app receives a notification with a PendingIntent that when clicked, opens the following screen:
#Composable
fun IntermediateMonthlyBillings(
onDataAcquired: (AllStatementsByYear) -> Unit,
myEwayLoggedInViewModel: MyEwayLoggedInViewModel = get()
) {
val statementsByYear by myEwayLoggedInViewModel.statementsByYear.observeAsState(null)
if (statementsByYear == null) {
GenericLoader(type = MyLoaderType.LIGHT_BACKGROUND)
} else {
Button(onClick = { onDataAcquired(statementsByYear!!) }) {
Text("hi")
}
}
}
The screen makes an API call to gather some data and at some point, the statementsByYear will be non-null. When that state is reached, I want to call the onDataAcquired() callback which will lead to a navigation instruction in the end. I need this to happen automatically but a simple if(statementsByYear != null) onDataAcquired() won't work since this will be triggered constantly. I couldn't find a side-effect that works for me either. Can you point me in the right direction?
In the example below I've added the button simply for testing that when used this way, everything works fine since the callback is triggered only once (upon clicking the button). The issue is how can I achieve this without the need for interactions.
LaunchedEffect with statementsByYear == null key would run twice . First when statement is true then it changes to false
LaunchedEffect(statementsByYear == null) {
if (statementsByYear == null) {
GenericLoader(type = MyLoaderType.LIGHT_BACKGROUND)
} else {
onDataAcquired(statementsByYear!!)
}
}
Although answer above is correct, instead of placing a Composable inside LaunchedEffect, it's a remember under the hood, i would go with
LaunchedEffect(statementsByYear != null) {
if (statementsByYear != null) {
onDataAcquired(statementsByYear!!)
}
}
if (statementsByYear == null) {
GenericLoader(type = MyLoaderType.LIGHT_BACKGROUND)
}

Kotlin Wi-Fi loss/bad signal during FTP transfer

I'm nearly done creating an app that sends txt files, containing scanned data, to an ftp server.
The issue that I'm currently struggling with is: what if my Wi-Fi has terrible signal or no signal at all.
I noticed that my 'isOnline()' check works fine and that if there is no internet, it alerts the user. However a few hours ago I tested the app in the basement and noticed that when the Wi-Fi signal has no bars, it still sends the data but it gets lost somewhere along the way.
Currently the flow of the data is as follow:
user presses 'send'
check internet and if true, continue
clear content list and send
the content to viewmodel
viewmodel checks internet again before
creating the txt files
txt files get sent via FTP code below.
private fun sendTXT(result: String) {
try {
val name = "00_VER${LocalDateTime.now().format(fileNameFormatter)}.txt"
val path = getApplication<Application>().applicationContext.filesDir.path
.toString() + name
val f = File(path)
val isNewFileCreated: Boolean = f.createNewFile()
if (isNewFileCreated) {
f.writeText(result, Charsets.UTF_8)
}
val ftpClient = FTPClient()
ftpClient.addProtocolCommandListener(PrintCommandListener(PrintWriter(System.out)))
ftpClient.connect("xxx.xx.xxx.xx", 21)
val reply: Int = ftpClient.replyCode
if (!FTPReply.isPositiveCompletion(reply)) {
ftpClient.disconnect()
throw IOException("Exception in connecting to FTP Server")
}
if (ftpClient.login("username", "pass")) {
ftpClient.enterLocalPassiveMode()
ftpClient.setFileType(FTP.BINARY_FILE_TYPE)
val inp = FileInputStream(f)
var directory = "/files/input"
ftpClient.changeWorkingDirectory(directory)
val result = ftpClient.storeFile(name, inp)
inp.close()
if (result) {
ftpClient.logout()
ftpClient.disconnect()
f.delete()
}
}
} catch (e: Exception) {
e.printStackTrace()
}
}
fun isOnline(context: Context): Boolean {
var result = false
val connectivityManager =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val networkCapabilities = connectivityManager.activeNetwork ?: return false
val actNw =
connectivityManager.getNetworkCapabilities(networkCapabilities) ?: return false
result = when {
actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
else -> false
}
} else {
connectivityManager.run {
connectivityManager.activeNetworkInfo?.run {
result = when (type) {
ConnectivityManager.TYPE_WIFI -> true
ConnectivityManager.TYPE_MOBILE -> true
ConnectivityManager.TYPE_ETHERNET -> true
else -> false
}
}
}
}
return result
}
I'm stuck at finding a way to make sure the data gets to the server. Is there a more advanced way to check for internet connectivity?
I was considering adding all the scan objects as JSON to sharedpreferences, and if at the end of the day the user notices a scan didn't make it through, they can look up the missing scan and resend it.
However this seems very unconventional and I'm pretty sure there must be a better way to handle things.

How does WorldEdit handle brushes?

I'm trying to find out how the Bukkit version of WorldEdit handles brushes. I've been looking at the source code on GitHub, but I couldn't find anythig useful. I've tried to recreate the effect, but I can only get it to work when I'm in interaction reach of the target block.
This is about as close as it gets in the source code:
} else if (action == Action.RIGHT_CLICK_AIR) {
if (we.handleRightClick(player)) {
event.setCancelled(true);
}
}
(WorldEdit/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditListener.java, line 143-147)
There are some other parts of code that get very close. I've also looked in /worldedit-core, but nothing there either.
Could someone help me here?
Edit: This is how I try to do it:
public static void onRightClick (PlayerInteractEvent event) {
if (event.getAction() == Action.RIGHT_CLICK_BLOCK) {
Location location = event.getClickedBlock().getLocation();
if (event.getItem() != null) {
if (event.getItem().getItemMeta().equals(ItemManager.wand.getItemMeta())) {
Player player = event.getPlayer();
player.getWorld().doStuff(location);
}
}
}
}
Edit #2: what I'm most curious about is: How does WE select the location to apply the brush if you are outside of interaction reach?
I needed to use BlockIterators for this. The final code looks like this:
public class BoomWandEvent implements Listener {
#EventHandler
public static void onRightClick (PlayerInteractEvent event) {
Player player = event.getPlayer();
if (event.getAction() == Action.RIGHT_CLICK_BLOCK || event.getAction() == Action.RIGHT_CLICK_AIR) {
if (player.getInventory().getItemInMainHand().equals(ItemManager.explosionWand)) {
Location eyePos = player.getEyeLocation();
BlockIterator raytracer = new BlockIterator(eyePos, 0.0D, player.getClientViewDistance() * 16);
while (raytracer.hasNext()) {
Location location = raytracer.next().getLocation();
if (player.getWorld().getBlockAt(location).getType() != Material.AIR && player.getWorld().getBlockAt(location).getType() != Material.CAVE_AIR && player.getWorld().getBlockAt(location).getType() != Material.VOID_AIR) {
player.getWorld().createExplosion(location, 4f);
return;
}
}
}
}
}
}
Thanks to Rogue for helping!

C++/winRT xaml ContentDialog example

The documentation shows this C# snippet:
async void DisplayDeleteFileDialog(){
ContentDialog deleteFileDialog = new ContentDialog{
Title = "Delete file permanently?",
Content = "If you delete this file, you won't be able to recover it. Do you want to delete it?",
PrimaryButtonText = "Delete",
CloseButtonText = "Cancel"
};
ContentDialogResult result = await deleteFileDialog.ShowAsync();
// Delete the file if the user clicked the primary button.
/// Otherwise, do nothing.
if (result == ContentDialogResult.Primary) {
// Delete the file.
}
else {
// The user clicked the CLoseButton, pressed ESC, Gamepad B, or the system back button.
// Do nothing.
}
}
What I'm requesting is a C++/winRT version of this snippet.
IAsyncAction Async()
{
ContentDialog dialog;
dialog.Title(box_value(L"title"));
dialog.Content(box_value(L"content"));
dialog.PrimaryButtonText(L"primary");
dialog.CloseButtonText(L"close");
auto result = co_await dialog.ShowAsync();
if (result == ContentDialogResult::Primary)
{
}
}
I wanted to open content dialog on button click so I tried the code snippet provided by Kenny Kerr. Everything seemed to work fine without error but when i clicked the button no dialog was seen. i fixed it by placing below code
dialog.XamlRoot(myButton().XamlRoot());
Before auto result = co_await dialog.ShowAsync() line.
ContentDialog.xaml, xaml.h, xaml.cpp should not have the name or classes
named Windows::UI::Xaml::Controls::ContentDialog!!! My name is
ContentDialog1
DirectXPage.xaml.cpp
void YourNamespace::DirectXPage::UpdateStatus(String^ strMessage,
NotifyType type)
{
switch (type)
{
case NotifyType::StatusMessage:
StatusBorder->Background = ref new
SolidColorBrush(Windows::UI::Colors::Green);
break;
case NotifyType::ErrorMessage:
StatusBorder->Background = ref new
SolidColorBrush(Windows::UI::Colors::Red);
break;
default:
break;
}
StatusBlock->Text = strMessage;
// Collapse the StatusBlock if it has no text to conserve real estate.
if (StatusBlock->Text != "")
{
StatusBorder->Visibility = Windows::UI::Xaml::Visibility::Visible;
StatusPanel->Visibility = Windows::UI::Xaml::Visibility::Visible;
}
else
{
StatusBorder->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
StatusPanel->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
}
// Raise an event if necessary to enable a screen reader to announce
the status update.
auto peer = dynamic_cast<FrameworkElementAutomationPeer^>
(FrameworkElementAutomationPeer::FromElement(StatusBlock));
if (peer != nullptr)
{
peer->RaiseAutomationEvent(AutomationEvents::LiveRegionChanged);
}
}
void YourNameSpace::DirectXPage::NotifyUser(Platform::String^ strMessage,
NotifyType type)
{
if (Dispatcher->HasThreadAccess)
{
UpdateStatus(strMessage, type);
}
else
{
Dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new
DispatchedHandler([strMessage, type, this]()
{
UpdateStatus(strMessage, type);
ContentDialog1^ dlg = ref new ContentDialog1();
dlg->ContentDialog_SetTitle(L"Error Message");
dlg->ContentDialog_SetTextBlock(L"All textures must be chosen from
the x64\\Release or Debug\\YourNamespace\\AppX\\Assets\\
(Folder or sub-Folders)");
Windows::Foundation::IAsyncOperation<ContentDialogResult>^ result =
dlg->ShowAsync();
if (result->GetResults() == ContentDialogResult::Primary) {}
if (result->GetResults() == ContentDialogResult::Secondary) {}
}));
}
}

Skype API help and acting very weird

I've made a big app for Skype called (Skype PWN4G3) one of its features are these lines of code:
//Control's
private void botOn_Click(object sender, EventArgs e)
{
if (toolStripLabel5.Text == "Not attached")
{
MessageBox.Show(notAttached, "Skype Pwnage - Info!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
else
{
botStop = false;
skype.Attach(7, false);
skype.MessageStatus += new _ISkypeEvents_MessageStatusEventHandler(skype_MessageStatus);
botOn.Text = "Running";
botOn.Enabled = false;
botOff.Enabled = true;
}
}
private void botOff_Click(object sender, EventArgs e)
{
botStop = true;
botOn.Text = "Enable";
botOn.Enabled = true;
botOff.Enabled = false;
}
//Function
private void skype_MessageStatus(ChatMessage msg, TChatMessageStatus status)
{
if (botStop == true)
{
}
else
{
try
{
string command = msg.Body.Remove(0, trigger.Length).ToLower();
string[] lines = richTextBox4.Text.Split('\n');
foreach (string ln in lines)
{
string[] commands = ln.Split(':');
if (radioButton6.Checked == true)
{
if (command.Contains(commands[0]))
{
listBox2.Items.Add(DateTime.Now +"> "+ commands[0]);
skype.SendMessage(msg.Sender.Handle, string.Format(commands[1]));
break;
}
}
if (radioButton4.Checked == true)
{
if (command == commands[0])
{
listBox2.Items.Add(DateTime.Now + "> " + commands[0]);
skype.SendMessage(msg.Sender.Handle, string.Format(commands[1]));
break;
}
}
}
}
catch (Exception err0)
{
}
}
}
Now my issue is this code work's great and it will reply auto to a person if they say a certain word. But it's very odd acting.
If you start the bot with the Skype window minimized and let it do it's work it work's great until you stop then start it or change the radio button from "Exact" to "Contains" then the next time it runs it will reply 2 times, then if you do the above again it will reply 3 times and so on,
One other very odd problem is that once you open your Skype window and view the messages from your side it re-seneds them all again. Any idea why?
And one more extra if anyone know's how I can stop / start this correctly that would be fantastic. And if you know how to make it so this will not listen to messages from chat groups and only PM's that would be great because right now it will listen to chat then send to User.Handle unless I can make some way to have it send into chat where the message was sent.
1) reply 2, 3 and more times - it seems that the problem is in skype.MessageStatus += ... that is being called each time you click on botOn. Either call -= or make sure that event subscription happens only once.
2) sending message again: skype_MessageStatus is being called for one message two times - check SKYPE4COMLib.TChatMessageStatus cmsSending/cmsReceived - when the message is delivered and cmsSent/cmsRead when target user clicks and actually views the message - so all you need to do is to check the value of SKYPE4COMLib.TChatMessageStatus Status
3) to make difference between direct messages and chat groups test in your code
SKYPE4COMLib.ChatMessage pMessage;
if (pMessage.Chat.Members.Count == 2)
{
// process direct messages
}
else if(pMessage.Chat.Members.Count > 2)
{
// do whatever you want to do to process chat messages
}