Posts in category “Programming”

[Solution] The argument type 'Consumer' can't be assigned to the parameter type 'PreferredSizeWidget?'.

The error occurs because AppBar expects a widget that implements the PreferredSizeWidget interface, but Consumer<NoteModel> does not directly implement this interface. To solve this, you need to return an AppBar from within the Consumer builder method.

Here’s how you can do it:

Scaffold(
  appBar: PreferredSize(
    preferredSize: Size.fromHeight(kToolbarHeight),
    child: Consumer<NoteModel>(
      builder: (context, noteModel, child) {
        return AppBar(
          title: Text(
            'Your Title',
            style: TextStyle(
              color: noteModel.isPrivate ? Colors.red : Colors.green,
            ),
          ),
        );
      },
    ),
  ),
  body: // Your other widgets,
);

In this approach, I wrapped the Consumer<NoteModel> inside a PreferredSize widget to ensure it adheres to the PreferredSizeWidget interface required by appBar.

This should resolve the error while allowing you to update only the AppBar based on changes in your NoteModel.

Glory to ChatGPT!

C# Linq:FirstOrDefault vs SingleOrDefault

In C#, both FirstOrDefault and SingleOrDefault are LINQ methods that operate on collections, but they serve different purposes:

FirstOrDefault

  • Purpose: Returns the first element in a collection that satisfies a specified condition, or the default value for the type if no such element is found.

  • Behavior:

    • If the collection contains multiple elements that satisfy the condition, it returns the first one.
    • If no elements satisfy the condition, it returns the default value (null for reference types, 0 for numeric types, etc.).
  • Use Case: When you're interested in getting the first match or a default value if none exist, and you don't care if there are multiple matches.

SingleOrDefault

  • Purpose: Returns the single element in a collection that satisfies a specified condition, or the default value for the type if no such element is found.

  • Behavior:

    • If the collection contains exactly one element that satisfies the condition, it returns that element.
    • If no elements satisfy the condition, it returns the default value.
    • If more than one element satisfies the condition, it throws an InvalidOperationException because the expectation is that there should be exactly one match.
  • Use Case: When you're expecting either one or zero matches, and multiple matches would indicate an error in your data or logic.

Summary

  • FirstOrDefault: Use when you want the first matching element or a default value, and multiple matches are acceptable.
  • SingleOrDefault: Use when you expect exactly one matching element or a default value, and multiple matches are an error.

fix TypeError: Instance of 'MappedListIterable': type 'MappedListIterable' is not a subtype of type 'FutureOr>'

--- a/lib/services/note_tag_service.dart
+++ b/lib/services/note_tag_service.dart
@@ -9,6 +9,5 @@ class NoteTagService {
   Future<Map<String, int>> getMyTagCloud() async {
     var apiResult = (await _noteTagApi.getMyTagCloud()).data;
     if (!apiResult['successful']) throw ApiException(apiResult);
-    return apiResult['data'].map((item) => {item['tag'] as String: item['count'] as int});
-  }
+    return { for (var item in apiResult['data']) item['tag'] as String : item['count'] as int };  }
+  }

C# inline regular expression syntax and usage

I found this brilliant answer at Stack overflow. It is way more clearer and useful than Microsoft's official one

You can use inline modifiers as follows:

// case insensitive match
Regex MyRegex = new Regex(@"(?i)[a-z]+");  // case insensitive match

or, inverse the meaning of the modifier by adding a minus-sign:

// case sensitive match
Regex MyRegex = new Regex(@"(?-i)[a-z]+");  // case sensitive match

or, switch them on and off:

// case sensitive, then case-insensitive match
Regex MyRegex = new Regex(@"(?-i)[a-z]+(?i)[k-n]+");

Alternatively, you can use the mode-modifier span syntax using a colon : and a grouping parenthesis, which scopes the modifier to only that group:

// case sensitive, then case-insensitive match
Regex MyRegex = new Regex(@"(?-i:[a-z]+)(?i:[k-n]+)");

You can use multiple modifiers in one go like this (?is-m:text), or after another, if you find that clearer (?i)(?s)(?-m)text (I don't). When you use the on/off switching syntax, be aware that the modifier works till the next switch, or the end of the regex. Conversely, using the mode-modified spans, after the span the default behavior will apply.

Finally: the allowed modifiers in .NET are (use a minus to invert the mode):

x allow whitespace and comments
s single-line mode
m multi-line mode
i case insensitivity
n only allow explicit capture (.NET specific)

A bash script `ci` to help you write commit message and commit with OPEN AI/Groq API

Writing commit message could be time-consuming if you want a good summrize. ChatGPT just released their cheapest but still powerful model gpt-4o-mini, we can use it to save our time and keep the commit message accurate.

Attention

I refine the following script time by time and keep the latest version on github. Click here to see the latest version!

You need to put your API KEY in environment variable OPENAI_API_KEY before running this script. You need to run git add first before running this ci script. If you don't want to bother adding first, change git diff --cached -w -b to git diff -w -b and add -a option in the commit command (the last line of the script)

#!/bin/bash

# Get git changes
changes=$(git diff --cached -w -b)

# Exit if no changes
if [ -z "$changes" ]; then
  echo "No changes to commit."
  exit 0
fi

# Set prompt template
prompt_template=$(cat <<-END
You are skilled at writing git commit messages and follow the conventional commits specification:

    refactor: for refactoring
    fix: for bug fixes
    minor: for minor changes
    ...

You will be given the changes from a 'git diff -w -b HEAD' command.
Please summarize all meaningful changes into one commit message, no more than 100 characters.
Respond only with the commit message. Do not mention unchanged aspects. Do not put doube quote in the message. Do not escape underscore characters.
DO REVISE THE MESSAGE THREE TIMES before sending it out. And again: no more than 100 characters!!!
Here are the changes:

END
)

prompt_template+="$changes"

# Build JSON request body using jq
request_body=$(jq -n --arg model "gpt-4o-mini-2024-07-18" --arg prompt "$prompt_template" \
  '{model: $model, messages: [{role:"system",content:"You are a programmer"},{role: "user", content: $prompt}], max_tokens: 32768, seed: 45, temperature: 0}')

# Use curl to request the OpenAI API to generate a commit message
response=$(curl -s --request POST \
  --url https://api.openai.com/v1/chat/completions \
  --header "Authorization: Bearer $OPENAI_API_KEY" \
  --header "Content-Type: application/json" \
  --data "$request_body")

# Extract commit message from the response
commit_message=$(echo "$response" | jq -r '.choices[0].message.content')

# Exit if the commit message is empty
if [ -z "$commit_message" ] || [ "$commit_message" == "null" ]; then
  echo 'failed to generate a commit message:'
  echo $response
  exit 1
fi

# Commit changes
git commit -m "$commit_message"
```bash
**2024-07-24 update**
## Free alternative provided by Groq

If you don't want to pay for the ChatGPT API, you can opt for the free alternative provided by [Groq](https://groq.com). To get started, simply sign up for a Groq account using Google Login. Once you've created your account, you can generate an API key by following this link: <https://console.groq.com/keys>. Finally, make a minor modification to your script, as outlined below.

Build JSON request body using jq

#request_body=$(jq -n arg model "gpt-4o-mini-2024-07-18" arg prompt "$prompt_template" \

'{model: $model, messages: [{role:"system",content:"You are a programmer"},{role: "user", content: $prompt}], max_tokens: 50, seed: 45, temperature: 0}')

#response=$(curl -s --request POST \

--url https://api.openai.com/v1/chat/completions \

--header "Authorization: Bearer $OPENAI_API_KEY" \

--header "Content-Type: application/json" \

--data "$request_body")

request_body=$(jq -n arg model "mixtral-8x7b-32768" arg prompt "$prompt_template"
'{model: $model, messages: [{role:"system",content:"You are a programmer"},{role: "user", content: $prompt}], max_tokens: 32768, stream: false, temperature: 0, top_p: 1, stop: null}')

Use curl to request the OpenAI API to generate a commit message

response=$(curl -s request POST
url https://api.groq.com/openai/v1/chat/completions
header "Authorization: Bearer $GROQ_API_KEY"
header "Content-Type: application/json"
--data "$request_body")